diff --git a/.circleci/config.yml b/.circleci/config.yml
index 353ee058..22d0f78b 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,17 +3,17 @@ orbs:
codecov: codecov/codecov@3.2.2
executor: machine
jobs:
- test:
+ build:
machine:
image: ubuntu-2004:202201-02
steps:
- checkout
- run:
name: build
- command: ./gradlew test
+ command: ./gradlew detekt assemble test --info --stacktrace
- codecov/upload:
file: build/reports/jacoco/test/*.xml
workflows:
build-workflow:
jobs:
- - test
+ - build
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000..57630235
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,41 @@
+
+>
+
+### Related Issue
+
+[Issue-X](https://github.com/janbarari/gradle-analytics-plugin/issues/X)
+
+### Motivation and Context
+
+
+### Description
+
+
+### Type of change
+
+- [ ] Feature
+- [ ] POC
+- [ ] Bug fix
+- [ ] Hot fix
+- [ ] Optimization
+- [ ] Refactor
+- [ ] Noref
+
+### Checklist
+- [ ] Are local unit tests passed?
+- [ ] Is Detekt passed?
+- [ ] Is code coverage affected?
+- [ ] Is any new test added?
+- [ ] Is CI workflow affected?
+- [ ] Is a next refactor needed?
+
+### How has this been tested?
+
+
+
+
+### Screenshots
+
+
+
+
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 2853c74b..4023a549 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@
.idea/
build/
.DS_Store
+temporary-notes.txt
+site/
diff --git a/LICENSE b/LICENSE
index 748d0618..7316ba37 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2022 Mehdi
+Copyright (c) 2022 Mehdi Janbarari (@janbarari)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index b81070e3..60b94852 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,10 @@
-# Gradle Analytics Plugin
+## Gradle Analytics Plugin
[![CircleCI](https://circleci.com/gh/janbarari/gradle-analytics-plugin/tree/develop.svg?style=svg)](https://circleci.com/gh/janbarari/gradle-analytics-plugin/tree/develop)
[![codecov](https://codecov.io/gh/janbarari/gradle-analytics-plugin/branch/develop/graph/badge.svg)](https://codecov.io/gh/janbarari/gradle-analytics-plugin)
-
-
-
-
-Request Feature or Report Bug
-
-Hey ๐, Mark this repo in your browser, see you soon ;D
+[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=janbarari_gradle-analytics-plugin&metric=alert_status)](https://sonarcloud.io/dashboard?id=janbarari_gradle-analytics-plugin)
-License
----
-Copyright ยฉ 2022 [Janbarari](https://github.com/janbarari)
-This project binaries and source code can be used according to the [MIT LICENSE](https://github.com/janbarari/gradle-analytics-plugin/blob/main/LICENSE).
+A free Gradle plugin to analyze your project builds. It provides unique visual and text metrics in HTML format.
+
+### Documentation is at janbarari.github.io/gradle-analytics-plugin
diff --git a/build.gradle.kts b/build.gradle.kts
index 59feb4b9..b63c636a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,20 +1,63 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+val pluginId: String by project
+val pluginDisplayName: String by project
+val pluginDescription: String by project
+val pluginImplementationClass: String by project
+val pluginDeclarationName: String by project
+val pluginGroupPackageName: String by project
+val pluginVersion: String by project
+val pluginWebsite: String by project
+val pluginVcsUrl: String by project
+val pluginTags: String by project
+
+@Suppress("DSL_SCOPE_VIOLATION")
plugins {
- kotlin("jvm") version "1.6.10"
+ kotlin("jvm") version(libs.versions.kotlin)
+ alias(libs.plugins.detekt)
+ `java-gradle-plugin`
+ `maven-publish`
jacoco
+ kotlin("kapt") version(libs.versions.kotlin)
+ id("com.gradle.plugin-publish") version "1.0.0-rc-1"
}
+group = pluginGroupPackageName
+version = pluginVersion
+
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
+ testImplementation(libs.mockk)
+
+ compileOnly(gradleApi())
+
+ implementation(kotlin("stdlib-jdk8"))
+ implementation(libs.sqlite.driver)
+ implementation(libs.mysql.driver)
+ implementation(libs.jetbrains.exposed.core)
+ implementation(libs.jetbrains.exposed.jdbc)
+ implementation(libs.moshi)
+ kapt(libs.moshi.codegen)
+ implementation(libs.commons.io)
+ implementation(libs.coroutines)
+ testImplementation(libs.coroutines.test)
+}
+
+tasks.withType().configureEach {
+ kotlinOptions {
+ jvmTarget = JavaVersion.VERSION_11.toString()
+ }
}
-tasks.withType {
- kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
+plugins.withType().configureEach {
+ extensions.configure {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
}
tasks.test {
@@ -28,4 +71,55 @@ tasks.jacocoTestReport {
csv.required.set(true)
html.required.set(true)
}
-}
\ No newline at end of file
+}
+
+publishing {
+ publications {
+ repositories {
+ mavenLocal()
+ }
+ }
+}
+
+pluginBundle {
+ website = pluginWebsite
+ vcsUrl = pluginVcsUrl
+ tags = "$pluginTags".split(",")
+}
+
+gradlePlugin {
+ plugins {
+ create(pluginDeclarationName) {
+ id = pluginId
+ displayName = pluginDisplayName
+ description = pluginDescription
+ implementationClass = pluginImplementationClass
+ }
+ }
+}
+
+tasks.wrapper {
+ distributionType = Wrapper.DistributionType.BIN
+}
+
+tasks.register("publishToLocal") {
+ doLast {
+ exec {
+ commandLine(
+ "./gradlew",
+ "detekt",
+ "build",
+ "test",
+ "publishToMavenLocal"
+ ).args("--info")
+ }
+ }
+}
+
+detekt {
+ config = files("detekt-config.yml")
+ buildUponDefaultConfig = true
+ source = files(
+ "src/main/kotlin"
+ )
+}
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 00000000..73991bcc
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,9 @@
+codecov:
+ require_ci_to_pass: yes
+ notify:
+ wait_for_ci: yes
+
+coverage:
+ precision: 2
+ round: down
+ range: 65...100
diff --git a/console-screenshot.png b/console-screenshot.png
new file mode 100644
index 00000000..0b7cd66c
Binary files /dev/null and b/console-screenshot.png differ
diff --git a/detekt-config.yml b/detekt-config.yml
new file mode 100644
index 00000000..e824d42f
--- /dev/null
+++ b/detekt-config.yml
@@ -0,0 +1,45 @@
+complexity:
+ active: true
+ TooManyFunctions:
+ active: true
+ excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**' ]
+ thresholdInFiles: 50
+ thresholdInClasses: 50
+ thresholdInInterfaces: 50
+ thresholdInObjects: 50
+ thresholdInEnums: 50
+ ignoreDeprecated: false
+ ignorePrivate: false
+ ignoreOverridden: false
+ LongParameterList:
+ active: false
+ NestedBlockDepth:
+ active: true
+ threshold: 6
+ LongMethod:
+ active: true
+ threshold: 75
+ ComplexMethod:
+ active: true
+ threshold: 25
+
+exceptions:
+ active: true
+ SwallowedException:
+ active: false
+ TooGenericExceptionCaught:
+ active: false
+
+style:
+ active: true
+ SerialVersionUIDInSerializableClass:
+ active: false
+ MagicNumber:
+ active: false
+ ReturnCount:
+ active: false
+ FunctionOnlyReturningConstant:
+ active: false
+ MaxLineLength:
+ active: true
+ maxLineLength: 128
diff --git a/docs/changelog.md b/docs/changelog.md
new file mode 100644
index 00000000..aa9cc0bd
--- /dev/null
+++ b/docs/changelog.md
@@ -0,0 +1,5 @@
+# Changelog
+
+## 1.0.0-beta1
+* Hello World :)
+
diff --git a/docs/contribution.md b/docs/contribution.md
new file mode 100644
index 00000000..d371ef4c
--- /dev/null
+++ b/docs/contribution.md
@@ -0,0 +1,2 @@
+# Contribution
+Gradle Analytics Plugin is Open Source and accepts contributions of new members, feel free to submit your PR and stay connected on the PR page and I will be glad to finalize and merge your PR in the upcoming release.
diff --git a/docs/getting-report.md b/docs/getting-report.md
new file mode 100644
index 00000000..50dfa82f
--- /dev/null
+++ b/docs/getting-report.md
@@ -0,0 +1,29 @@
+# Getting Report
+Gradle Analytics Plugin uses daily basis data to generate reports. So you could use the below instructions to generate your build analysis.
+
+Execute Gradle Task
+```Gradle
+./gradlew reportAnalytics --task="REQUESTED_TASK" --branch="BRANCH_NAME" --period="can be like today, s:yyyy/MM/dd,e:yyyy/MM/dd, 1y, 4m, 38d, 3m 06d"
+```
+
+
+!!! Note ""
+
+ --period Examples
+
+ - today - Generates report only for the current day.
+ - 1d - Generates report from 1 day ago till now.
+ - 1m 3d - Generates report from 1 month and 3 days ago till now.
+ - 1y - Generates report from 1 year ago till now.
+ - s:2022/03/24,e:2022/04/25 - Generates report from `2022/03/24` till `2022/04/25`.
+
+
+ Plugin only holds the metrics results in the caching database up to one year.
+
+
+
+To understand the metrics and report that plugin provides, It is required to understand Gradle basics and how this build
+system works.
https://docs.gradle.org/current/userguide/what_is_gradle.html
+
+
+
diff --git a/docs/img/build-status.png b/docs/img/build-status.png
new file mode 100644
index 00000000..3d760e76
Binary files /dev/null and b/docs/img/build-status.png differ
diff --git a/docs/img/cache-hit.png b/docs/img/cache-hit.png
new file mode 100644
index 00000000..61c699f7
Binary files /dev/null and b/docs/img/cache-hit.png differ
diff --git a/docs/img/configuration-process.png b/docs/img/configuration-process.png
new file mode 100644
index 00000000..0a86368c
Binary files /dev/null and b/docs/img/configuration-process.png differ
diff --git a/docs/img/dependency-details.png b/docs/img/dependency-details.png
new file mode 100644
index 00000000..0501b120
Binary files /dev/null and b/docs/img/dependency-details.png differ
diff --git a/docs/img/dependency-resolve-process.png b/docs/img/dependency-resolve-process.png
new file mode 100644
index 00000000..47245f1f
Binary files /dev/null and b/docs/img/dependency-resolve-process.png differ
diff --git a/docs/img/execution-process.png b/docs/img/execution-process.png
new file mode 100644
index 00000000..2b24c3b3
Binary files /dev/null and b/docs/img/execution-process.png differ
diff --git a/docs/img/initialization-process.png b/docs/img/initialization-process.png
new file mode 100644
index 00000000..2576869d
Binary files /dev/null and b/docs/img/initialization-process.png differ
diff --git a/docs/img/module-execution-process-1.png b/docs/img/module-execution-process-1.png
new file mode 100644
index 00000000..7e4415d6
Binary files /dev/null and b/docs/img/module-execution-process-1.png differ
diff --git a/docs/img/module-execution-process-2.png b/docs/img/module-execution-process-2.png
new file mode 100644
index 00000000..d1870b84
Binary files /dev/null and b/docs/img/module-execution-process-2.png differ
diff --git a/docs/img/modules-build-heatmap.png b/docs/img/modules-build-heatmap.png
new file mode 100644
index 00000000..b50f5f9c
Binary files /dev/null and b/docs/img/modules-build-heatmap.png differ
diff --git a/docs/img/modules-crash-count.png b/docs/img/modules-crash-count.png
new file mode 100644
index 00000000..082972c5
Binary files /dev/null and b/docs/img/modules-crash-count.png differ
diff --git a/docs/img/modules-dependency-graph.png b/docs/img/modules-dependency-graph.png
new file mode 100644
index 00000000..ae50c4cf
Binary files /dev/null and b/docs/img/modules-dependency-graph.png differ
diff --git a/docs/img/modules-execution-timeline.png b/docs/img/modules-execution-timeline.png
new file mode 100644
index 00000000..94fcf836
Binary files /dev/null and b/docs/img/modules-execution-timeline.png differ
diff --git a/docs/img/modules-method-count.png b/docs/img/modules-method-count.png
new file mode 100644
index 00000000..15582c84
Binary files /dev/null and b/docs/img/modules-method-count.png differ
diff --git a/docs/img/modules-source-count.png b/docs/img/modules-source-count.png
new file mode 100644
index 00000000..da2439ff
Binary files /dev/null and b/docs/img/modules-source-count.png differ
diff --git a/docs/img/modules-source-size.png b/docs/img/modules-source-size.png
new file mode 100644
index 00000000..6c46c95d
Binary files /dev/null and b/docs/img/modules-source-size.png differ
diff --git a/docs/img/non-cacheable-tasks.png b/docs/img/non-cacheable-tasks.png
new file mode 100644
index 00000000..7786ca28
Binary files /dev/null and b/docs/img/non-cacheable-tasks.png differ
diff --git a/docs/img/overall-build-process.png b/docs/img/overall-build-process.png
new file mode 100644
index 00000000..0f6a4784
Binary files /dev/null and b/docs/img/overall-build-process.png differ
diff --git a/docs/img/parallel-execution-rate.png b/docs/img/parallel-execution-rate.png
new file mode 100644
index 00000000..941d1880
Binary files /dev/null and b/docs/img/parallel-execution-rate.png differ
diff --git a/docs/img/plugin-logo.png b/docs/img/plugin-logo.png
new file mode 100755
index 00000000..404a4c24
Binary files /dev/null and b/docs/img/plugin-logo.png differ
diff --git a/docs/img/successful-build-rate.png b/docs/img/successful-build-rate.png
new file mode 100644
index 00000000..5a8a3d47
Binary files /dev/null and b/docs/img/successful-build-rate.png differ
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..bec0d2dc
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,150 @@
+
+
+# Gradle Analytics Plugin
+[![CircleCI](https://circleci.com/gh/janbarari/gradle-analytics-plugin/tree/develop.svg?style=svg)](https://circleci.com/gh/janbarari/gradle-analytics-plugin/tree/develop)
+[![codecov](https://codecov.io/gh/janbarari/gradle-analytics-plugin/branch/develop/graph/badge.svg)](https://codecov.io/gh/janbarari/gradle-analytics-plugin)
+[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=janbarari_gradle-analytics-plugin&metric=alert_status)](https://sonarcloud.io/dashboard?id=janbarari_gradle-analytics-plugin)
+
+A free Gradle plugin to analyze your project builds. It provides unique visual and text metrics in HTML format.
+
+
+Below you can see the metrics provided by the plugin ๐
+
+!!! Note ""
+
+ To understand the metrics and report that plugin provides, It is required to understand Gradle basics and how this build
+ system works.
https://docs.gradle.org/current/userguide/what_is_gradle.html
+
+## Build Status
+An overview of metrics results of the `requested task` in the build processes over the aforementioned period.
+
+![](img/build-status.png)
+
+
+## Initialization Process
+Gradle supports single and multi-project builds. During the initialization process, Gradle determines which projects are going to take part in the build, and creates a Project instance for each of these projects. By adding more projects or modules the process will take longer.
+
+It denotes the average initialization process time over the report period.
+
+![](img/initialization-process.png)
+
+
+## Configuration Process
+Constructs and configures the task graph for the build and then determines which tasks need to run and in which order, based on the task the user wants to run. Be careful about the tasks you register to the project and try to make them cacheable.
+
+It shows the average configuration process time over the report period.
+
+![](img/configuration-process.png)
+
+
+## Dependency Resolve Process
+Downloading and resolving the project's dependencies is one of the configuration process' stages. If the project has multiple third-party libraries dependencies, make sure that you have a good network speed.
+
+It represents the download(Dependency Resolve) process average duration during the report period.
+
+![](img/dependency-resolve-process.png)
+
+
+## Execution Process
+Runs the selected tasks based on `requested tasks` task tree. Gradle executes `requested task` according to the dependency order.
+
+It represents the Execution Process average duration during the report period.
+
+![](img/execution-process.png)
+
+
+## Modules Execution Process
+It represents the (Median) process execution time of each module over the report period.
+
+![](img/module-execution-process-1.png)
+![](img/module-execution-process-2.png)
+
+
+## Overall Build Process
+It represents the average duration of overall build process.
+
+![](img/overall-build-process.png)
+
+
+## Modules Source Count
+It represents the project and its modules source file count. (files with extension of kt, java).
+
+![](img/modules-source-count.png)
+
+
+## Modules Source Size
+It represents the project and its modules source file size.
+
+![](img/modules-source-size.png)
+
+
+## Modules Method Count
+It represents the project and its modules source method count.
+
+![](img/modules-method-count.png)
+
+
+## Cache Hit
+Gradle creates a cache for the executed task to be reused in the next incremental builds, the more cached tasks lead to faster builds.
+
+It represents the project and modules tasks average cache hit rate (tasks run with FROM_CACHE or UP_TO_DATE).
+
+![](img/cache-hit.png)
+
+
+## Successful Build Rate
+It represents the successful build rate of the `requested task` during the report period.
+
+![](img/successful-build-rate.png)
+
+
+## Modules Crash Count
+It represents how many build failures happened during the `requested task` execution caused by project modules during the report period.
+
+![](img/modules-crash-count.png)
+
+
+## Parallel Execution Rate
+Gradle uses CPU cores to execute more tasks simultaneously, leading to a faster build.
+
+It represents a rate that how much time was saved in the execution of the build process with parallel execution versus real elapsed time.
+
+![](img/parallel-execution-rate.png)
+
+
+## Modules Dependency Graph
+It represents the project module's dependency graph and their connection types.
+
+Modules have colors that warm colors have represents more dependent modules, and It is recommended to have fewer warm color modules because by applying any change in these modules, all other dependent modules need to rebuild and this cost more time and resources from your machines and put the builds in queue.
+
+![](img/modules-dependency-graph.png)
+
+
+## Modules Execution Timeline
+It represents the latest modules execution process timeline graph.
+
+![](img/modules-execution-timeline.png)
+
+
+## Modules Build Heatmap
+This plugin uses `Modules Cache Usage` and `Modules Dependency Graph` to generate this metric that shows how many times a module was built during the report period.
+
+Each bar has the name of the module and the number of dependent modules, smaller warm bars lead to faster builds as those modules with warm colors have more dependent modules.
+
+In addition, it helps to modify the modular structure by tracing the graph and finding the cause to avoid rebuilding the modules that are most shared with others.
+
+![](img/modules-build-heatmap.png)
+
+
+## Dependency Details
+It represents the project(including all modules) dependencies with their sizes.
+
+![](img/dependency-details.png)
+
+
+## Non-cacheable Tasks
+These tasks are executed in the `requested task` tree without being cached. Try to avoid creating tasks that are not cacheable. Track this chart and detect tasks that are time-consuming.
+
+![](img/non-cacheable-tasks.png)
+
+
\ No newline at end of file
diff --git a/docs/license.md b/docs/license.md
new file mode 100644
index 00000000..fe3467d9
--- /dev/null
+++ b/docs/license.md
@@ -0,0 +1,21 @@
+# License
+MIT License
+Copyright © 2022 Mehdi Janbarari (@janbarari)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/docs/privacy-policy.md b/docs/privacy-policy.md
new file mode 100644
index 00000000..c1befdbe
--- /dev/null
+++ b/docs/privacy-policy.md
@@ -0,0 +1,2 @@
+# Privacy Policy
+Gradle Analytics Plugin does NOT send any collected data to any server apart from the user's own database config. It uses offline HTML renders to provide the analytics, So there is no need to upload any data from the database.
\ No newline at end of file
diff --git a/docs/report-bug.md b/docs/report-bug.md
new file mode 100644
index 00000000..7e602a55
--- /dev/null
+++ b/docs/report-bug.md
@@ -0,0 +1,4 @@
+# Report Bug
+I appreciate reporting the bugs and crashes in the plugin. In order to submit please use either below ways:
+
+[Github Link](https://github.com/janbarari/gradle-analytics-plugin/issues/new?title=RB:) or [Send Me Email](mailto:mehdi.janbarari@outlook.com?subject=[GAP]%20Report%20Bug)
diff --git a/docs/request-feature.md b/docs/request-feature.md
new file mode 100644
index 00000000..4346242d
--- /dev/null
+++ b/docs/request-feature.md
@@ -0,0 +1,4 @@
+# Request Feature
+I thankfully appreciate to send me your ideas about new features. In order to submit your ideas please use the below ways:
+
+[Github Link](https://github.com/janbarari/gradle-analytics-plugin/issues/new?title=RF:) or [Send Me Email](mailto:mehdi.janbarari@outlook.com?subject=[GAP]%20Request%20Feature)
diff --git a/docs/setup.md b/docs/setup.md
new file mode 100644
index 00000000..a42f1bed
--- /dev/null
+++ b/docs/setup.md
@@ -0,0 +1,107 @@
+# Setup
+To set up the plugin in your project, follow the below instructions:
+
+### Step 1
+Make sure your project uses Git VCS.
+!!! Note ""
+
+ Gradle Analytics Plugin uses Git terminal to get the branch names and latest HEAD commit hash.
+ so It is required for your project to use Git VCS.
+
+
+
+### Step 2
+Apply the Gradle Plugin to the root of your project.
+=== "Kotlin"
+ ``` kotlin
+ plugins {
+ id("io.github.janbarari.gradle-analytics-plugin") version "1.0.0-beta1"
+ }
+ ```
+=== "Groovy"
+ ``` groovy
+ plugins {
+ id "io.github.janbarari.gradle-analytics-plugin" version "1.0.0-beta1"
+ }
+ ```
+[For legacy plugin application, see the Gradle Plugin Portal.](https://plugins.gradle.org/plugin/io.github.janbarari.gradle-analytics-plugin)
+
+
+### Step 3
+Add plugin configuration in the root of your project.
+
+=== "Kotlin"
+ ``` kotlin
+ gradleAnalyticsPlugin {
+ database {
+ local = sqlite {
+ path = "DATABASE_PATH"
+ name = "DATABASE_NAME"
+ user = "DATABASE_USER"
+ password = "DATABASE_PASSWORD"
+ }
+ ci = mysql {
+ host = "MYSQL_DATABASE_HOST",
+ name = "MYSQL_DATABASE_NAME",
+ user = "MYSQL_DATABASE_USER",
+ password = "MYSQL_DATABASE_PASSWORD"
+ port = MYSQL_DATABASE_PORT // Default is 3306
+ }
+ }
+
+ trackingTasks = listOf(
+ // Add your requested tasks to be analyzed, Example:
+ ":app:assembleDebug"
+ )
+
+ trackingBranches = listOf(
+ // requested tasks only analyzed in the branches you add here, Example:
+ "master",
+ "develop"
+ )
+
+ outputPath = "OUTPUT_REPORT_PATH"
+ }
+ ```
+=== "Groovy"
+ ``` groovy
+ gradleAnalyticsPlugin {
+ database {
+ local = sqlite {
+ path = "DATABASE_PATH"
+ name = "DATABASE_NAME"
+ user = "DATABASE_USER"
+ password = "DATABASE_PASSWORD"
+ }
+ ci = mysql {
+ host = "MYSQL_DATABASE_HOST",
+ name = "MYSQL_DATABASE_NAME",
+ user = "MYSQL_DATABASE_USER",
+ password = "MYSQL_DATABASE_PASSWORD"
+ port = MYSQL_DATABASE_PORT // Default is 3306
+ }
+ }
+
+ trackingTasks = [
+ // Add your requested tasks to be analyzed, Example:
+ ":app:assembleDebug"
+ ]
+
+ trackingBranches = [
+ // requested tasks only analyzed in the branches you add here, Example:
+ "master",
+ "develop"
+ ]
+
+ outputPath = "OUTPUT_REPORT_PATH"
+ }
+ ```
+
+Important Notes
+
+- If you don't have a sqlite database, the plugin will create one automatically. You only need to the `name` and `path` for it.
+- You can choose both `sqlite / mysql` for `local` or `ci`.
+- You can skip `local` or `ci` database if you don't need analytics on each of them.
+- If you use `ci` make sure the `CI=true` environment variable exists in your CI system environments.
+
+
diff --git a/docs/special-thanks.md b/docs/special-thanks.md
new file mode 100644
index 00000000..e10da739
--- /dev/null
+++ b/docs/special-thanks.md
@@ -0,0 +1,7 @@
+# Special Thanks
+I am very proud to give special thanks to those around me in making and presenting this open source project.
+
+I am grateful to Yazdan Sharifi(@yazdan-sharifi2020), who helped write the plugin report renders.
+
+Best regards,
+Mehdi
diff --git a/docs/support.md b/docs/support.md
new file mode 100644
index 00000000..99809751
--- /dev/null
+++ b/docs/support.md
@@ -0,0 +1,15 @@
+# Support
+Gradle Analytics Plugin is Open Source and completely free, I spent more than a year analyzing build bottlenecks and finding a way to track them, and finally implemented it into the plugin.
+
+Of course, this project will be continued as a free open-source project. But to give me some energy, you can use either below ways to support me.
+
+Send me Crypto
+Bitcoin: bc1q8ecepuax6je6s70j4l76nr978w34msc929sfuf
+
+Tether(ERC20): 0x2f23a4F4502C5e699777f3F89da6Ba965C7800FF
+
+Don't forget to tap the โญ button on the project [Github link](https://github.com/janbarari/gradle-analytics-plugin).
+
+
+Thanks,
+Mehdi
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 7fc6f1ff..3a600d2f 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1 +1,13 @@
kotlin.code.style=official
+org.gradle.warning.mode=all
+
+pluginWebsite = https://github.com/janbarari/gradle-analytics-plugin
+pluginVcsUrl = https://github.com/janbarari/gradle-analytics-plugin.git
+pluginId = io.github.janbarari.gradle-analytics-plugin
+pluginDisplayName = gradle-analytics-plugin
+pluginDescription = A free Gradle plugin to analyze your project builds. It provides unique visual and text metrics in HTML format.
+pluginTags = kotlin,plugin,analytics,analysis,gradle,gradle-plugin,gradle-plugins,build,metrics,performance,tracker
+pluginImplementationClass = io.github.janbarari.gradle.analytics.GradleAnalyticsPlugin
+pluginDeclarationName = gradleAnalyticsPlugin
+pluginGroupPackageName = io.github.janbarari
+pluginVersion = 1.0.0-beta1
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 00000000..5010b008
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,25 @@
+[versions]
+kotlin = "1.6.20"
+detekt = "1.20.0-RC2"
+sqlite_driver = "3.36.0.3"
+mysql_driver = "8.0.29"
+jetbrains_exposed = "0.38.1"
+moshi = "1.13.0"
+commons-io = "2.11.0"
+mockk = "1.12.4"
+coroutines = "1.6.3"
+
+[libraries]
+sqlite_driver = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite_driver" }
+mysql_driver = { module = "mysql:mysql-connector-java", version.ref = "mysql_driver" }
+jetbrains_exposed_core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "jetbrains_exposed" }
+jetbrains_exposed_jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "jetbrains_exposed" }
+moshi = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi" }
+moshi-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi" }
+commons-io = { module = "commons-io:commons-io", version.ref = "commons-io" }
+mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
+coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
+coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
+
+[plugins]
+detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
old mode 100644
new mode 100755
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 05679dc3..92f06b50 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 00000000..507bb448
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,46 @@
+site_name: Gradle Analytics Plugin
+site_url: https://janbarari.github.io/gradle-analytics-plugin/
+repo_name: Gradle Analytics Plugin
+repo_url: https://github.com/janbarari/gradle-analytics-plugin/
+site_description: A free Gradle plugin to analyze your project builds. It provides unique visual and text metrics in the HTML format.
+site_author: Mehdi Janbarari
+
+nav:
+ - Overview: index.md
+ - Setup: setup.md
+ - Getting Report: getting-report.md
+ - Changelog: changelog.md
+ - Support: support.md
+ - Contribution: contribution.md
+ - Privacy & Policy: privacy-policy.md
+ - Request Feature: request-feature.md
+ - Report Bug: report-bug.md
+ - Special Thanks: special-thanks.md
+ - License: license.md
+
+theme:
+ name: material
+ palette:
+ primary: white
+ logo: img/plugin-logo.png
+ favicon: img/plugin-logo.png
+ features:
+ - header.autohide
+
+markdown_extensions:
+ - codehilite
+ - admonition
+ - pymdownx.superfences
+ - pymdownx.inlinehilite
+ - pymdownx.tabbed:
+ alternate_style: true
+
+copyright: Made with ๐งก for everyone | Copyright © 2022
+
+extra:
+ generator: false
+ social:
+ - icon: fontawesome/brands/twitter
+ link: https://twitter.com/medicodroid
+ - icon: fontawesome/brands/github
+ link: https://github.com/janbarari
\ No newline at end of file
diff --git a/plugin-logo.png b/plugin-logo.png
old mode 100644
new mode 100755
diff --git a/privacy-policy.md b/privacy-policy.md
new file mode 100644
index 00000000..c23fb6a3
--- /dev/null
+++ b/privacy-policy.md
@@ -0,0 +1,4 @@
+# Privacy policy
+
+This plugin does NOT send any collected data to any server apart from the user's own database config. This plugin uses
+offline HTML renders to provide the analytics, So there is no need to upload any data from the database.
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index a24240d5..4190815c 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,2 +1 @@
rootProject.name = "gradle-analytics-plugin"
-
diff --git a/src/main/kotlin/Mehdi.kt b/src/main/kotlin/Mehdi.kt
deleted file mode 100644
index 51212fda..00000000
--- a/src/main/kotlin/Mehdi.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-class Mehdi {
- fun getMehdi(): String {
- return "Mehdi"
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/io/github/janbarari/gradle/ExcludeJacocoGenerated.kt b/src/main/kotlin/io/github/janbarari/gradle/ExcludeJacocoGenerated.kt
new file mode 100644
index 00000000..1e537ec9
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/ExcludeJacocoGenerated.kt
@@ -0,0 +1,40 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle
+
+/**
+ * In order to have reliable code coverage sometimes it's needed to exclude some
+ * functions or classes that their lifecycle is based on the framework and not
+ * in developer hand.
+ *
+ * Since Jacoco 0.8.2, developers can exclude classes and methods by annotating
+ * them with a custom annotation with the following properties:
+ *
+ * 1- The name of the annotation should include the 'Generated' keyword.
+ * 2- The retention policy of annotation should be runtime or class.
+ */
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.TYPE, AnnotationTarget.FUNCTION,
+ AnnotationTarget.CLASS, AnnotationTarget.FIELD)
+annotation class ExcludeJacocoGenerated
diff --git a/src/main/kotlin/io/github/janbarari/gradle/IncompatibleVersionException.kt b/src/main/kotlin/io/github/janbarari/gradle/IncompatibleVersionException.kt
new file mode 100644
index 00000000..4212cc51
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/IncompatibleVersionException.kt
@@ -0,0 +1,34 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle
+
+@ExcludeJacocoGenerated
+class IncompatibleVersionException(
+ private val title: String,
+ private val minimumRequiredVersion: String
+) : Throwable() {
+
+ override val message: String
+ get() = "$title is compatible with Gradle version $minimumRequiredVersion and above."
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/NotAccessibleGitTerminalException.kt b/src/main/kotlin/io/github/janbarari/gradle/NotAccessibleGitTerminalException.kt
new file mode 100644
index 00000000..ce6f9211
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/NotAccessibleGitTerminalException.kt
@@ -0,0 +1,28 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle
+
+@ExcludeJacocoGenerated
+class NotAccessibleGitTerminalException(title: String): Throwable(
+ message = "$title works only on projects which use Git."
+)
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/DatabaseConfig.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/DatabaseConfig.kt
new file mode 100644
index 00000000..c33d301d
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/DatabaseConfig.kt
@@ -0,0 +1,93 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics
+
+import groovy.lang.Closure
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.database.DatabaseConnection
+import io.github.janbarari.gradle.analytics.database.MySqlDatabaseConnection
+import io.github.janbarari.gradle.analytics.database.SqliteDatabaseConnection
+
+@ExcludeJacocoGenerated
+class DatabaseConfig @JvmOverloads constructor() : java.io.Serializable {
+
+ /**
+ * It is the database config of user local machine, this variable should be initialized
+ * with one of the database configs that the plugin supports.
+ */
+ var local: DatabaseConnection? = null
+
+ /**
+ * It is the database config of CI. Should be initialized
+ * with one of the database configs that the plugin supports. Keep in mind that
+ * if this variable is initialized, then the plugin only uses this database
+ * config on CI.
+ *
+ * Note: please make sure the CI has an environment variable named `CI`.
+ */
+ var ci: DatabaseConnection? = null
+
+ /**
+ * Factory method for create a new instance
+ * of [io.github.janbarari.gradle.analytics.data.database.config.MySqlDatabaseConfig].
+ */
+ fun mysql(block: MySqlDatabaseConnection.() -> Unit): MySqlDatabaseConnection {
+ return MySqlDatabaseConnection {
+ also(block)
+ }
+ }
+
+ /**
+ * Factory method for create a new instance
+ * of [io.github.janbarari.gradle.analytics.data.database.config.MySqlDatabaseConfig].
+ */
+ fun mysql(closure: Closure<*>): MySqlDatabaseConnection {
+ val temp = MySqlDatabaseConnection { }
+ closure.delegate = temp
+ closure.call()
+ return temp
+ }
+
+ /**
+ * Factory method for create a new instance
+ * of [io.github.janbarari.gradle.analytics.data.database.config.SqliteDatabaseConfig].
+ */
+ fun sqlite(block: SqliteDatabaseConnection.() -> Unit): SqliteDatabaseConnection {
+ return SqliteDatabaseConnection {
+ also(block)
+ }
+ }
+
+ /**
+ * Factory method for create a new instance
+ * of [io.github.janbarari.gradle.analytics.data.database.config.SqliteDatabaseConfig].
+ */
+ fun sqlite(closure: Closure<*>): SqliteDatabaseConnection {
+ val temp = SqliteDatabaseConnection { }
+ closure.delegate = temp
+ closure.call()
+ return temp
+ }
+
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/GradleAnalyticsPlugin.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/GradleAnalyticsPlugin.kt
new file mode 100644
index 00000000..4baa5551
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/GradleAnalyticsPlugin.kt
@@ -0,0 +1,108 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics
+
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.IncompatibleVersionException
+import io.github.janbarari.gradle.NotAccessibleGitTerminalException
+import io.github.janbarari.gradle.analytics.reporttask.ReportAnalyticsTask
+import io.github.janbarari.gradle.analytics.scanner.ScannerUtils
+import io.github.janbarari.gradle.utils.GitUtils
+import io.github.janbarari.gradle.utils.ProjectUtils
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.build.event.BuildEventsListenerRegistry
+import javax.inject.Inject
+
+/**
+ * A free Gradle plugin for analytics of your projects. Provides unique visual and
+ * text metrics in HTML format.
+ */
+@ExcludeJacocoGenerated
+class GradleAnalyticsPlugin @Inject constructor(
+ private val registry: BuildEventsListenerRegistry
+) : Plugin {
+
+ companion object {
+ const val PLUGIN_NAME = "gradleAnalyticsPlugin"
+ const val PLUGIN_VERSION = "1.0.0-beta1"
+ }
+
+ /**
+ * Gradle will invoke this function once the plugin is added into the project build script.
+ */
+ override fun apply(project: Project) {
+ ensureProjectGradleCompatible()
+ ensureGitTerminalAccessible()
+ val config = setupPluginConfig(project)
+ registerTasks(config)
+ ScannerUtils.setupScannerServices(config, registry)
+ }
+
+ /**
+ * The plugin is compatible with Gradle version 6.1 and above, This function ensures
+ * the plugin Gradle version is compatible with the user project version.
+ *
+ * @throws io.github.janbarari.gradle.IncompatibleVersionException when the Gradle version is not compatible.
+ */
+ @kotlin.jvm.Throws(IncompatibleVersionException::class)
+ private fun ensureProjectGradleCompatible() {
+ val requiredGradleVersion = ProjectUtils.GradleVersions.V6_1
+ if (!ProjectUtils.isCompatibleWith(requiredGradleVersion)) {
+ throw IncompatibleVersionException(PLUGIN_NAME, requiredGradleVersion.versionNumber)
+ }
+ }
+
+ /**
+ * The plugin only works on projects which use Git. This function ensures the Git terminal accessible in project directory.
+ */
+ @kotlin.jvm.Throws(NotAccessibleGitTerminalException::class)
+ private fun ensureGitTerminalAccessible() {
+ try {
+ GitUtils.currentBranch()
+ } catch (e: Throwable) {
+ throw NotAccessibleGitTerminalException(PLUGIN_NAME)
+ }
+ }
+
+ /**
+ * Setups plugin config.
+ *
+ * Note: extension will be initialized after projectsEvaluated(configuration process).
+ */
+ private fun setupPluginConfig(project: Project): GradleAnalyticsPluginConfig {
+ return project.extensions.create(
+ PLUGIN_NAME,
+ GradleAnalyticsPluginConfig::class.java,
+ project
+ )
+ }
+
+ /**
+ * Registers the plugin custom tasks.
+ */
+ private fun registerTasks(config: GradleAnalyticsPluginConfig) {
+ ReportAnalyticsTask.register(config)
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/GradleAnalyticsPluginConfig.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/GradleAnalyticsPluginConfig.kt
new file mode 100644
index 00000000..b31878ee
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/GradleAnalyticsPluginConfig.kt
@@ -0,0 +1,56 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics
+
+import groovy.lang.Closure
+import io.github.janbarari.gradle.analytics.database.DatabaseConnection
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import org.gradle.api.NamedDomainObjectContainer
+import org.gradle.api.Project
+
+/**
+ * Configuration options for the [io.github.janbarari.gradle.analytics.GradleAnalyticsPlugin].
+ */
+@ExcludeJacocoGenerated
+open class GradleAnalyticsPluginConfig(val project: Project) {
+
+ private var databaseConfig: DatabaseConfig = DatabaseConfig()
+
+ var trackingTasks: List = listOf()
+
+ var trackingBranches: List = listOf()
+
+ var outputPath: String = project.rootProject.buildDir.absolutePath
+
+ fun database(closure: Closure<*>) {
+ closure.delegate = databaseConfig
+ closure.call()
+ }
+
+ fun database(block: DatabaseConfig.() -> Unit) {
+ databaseConfig = DatabaseConfig().also(block)
+ }
+
+ fun getDatabaseConfig(): DatabaseConfig = databaseConfig
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/data/DatabaseRepositoryImp.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/data/DatabaseRepositoryImp.kt
new file mode 100644
index 00000000..4bcdb2ce
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/data/DatabaseRepositoryImp.kt
@@ -0,0 +1,254 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.data
+
+import com.squareup.moshi.Moshi
+import io.github.janbarari.gradle.analytics.database.Database
+import io.github.janbarari.gradle.analytics.database.ResetAutoIncremental
+import io.github.janbarari.gradle.analytics.database.table.MetricTable
+import io.github.janbarari.gradle.analytics.database.table.SingleMetricTable
+import io.github.janbarari.gradle.analytics.database.table.TemporaryMetricTable
+import io.github.janbarari.gradle.analytics.database.table.TemporaryMetricTable.value
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetricJsonAdapter
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.extension.separateElementsWithSpace
+import io.github.janbarari.gradle.utils.DateTimeUtils
+import org.jetbrains.exposed.sql.ResultRow
+import org.jetbrains.exposed.sql.SortOrder
+import org.jetbrains.exposed.sql.and
+import org.jetbrains.exposed.sql.deleteAll
+import org.jetbrains.exposed.sql.deleteWhere
+import org.jetbrains.exposed.sql.insert
+import org.jetbrains.exposed.sql.select
+import org.jetbrains.exposed.sql.update
+
+class DatabaseRepositoryImp(
+ private val db: Database,
+ private val branch: String,
+ private val requestedTasks: String,
+ private val moshi: Moshi
+) : DatabaseRepository {
+
+ private var jsonAdapter: BuildMetricJsonAdapter = BuildMetricJsonAdapter(moshi)
+
+ override fun saveNewMetric(metric: BuildMetric): Long {
+ return db.transaction {
+ val queryResult = MetricTable.insert {
+ it[createdAt] = metric.createdAt
+ it[value] = jsonAdapter.toJson(metric)
+ it[branch] = metric.branch
+ it[requestedTasks] = metric.requestedTasks.separateElementsWithSpace()
+ }
+ dropOutdatedMetrics()
+ return@transaction queryResult[MetricTable.number]
+ }
+ }
+
+ override fun saveTemporaryMetric(metric: BuildMetric): Long {
+ return db.transaction {
+ val queryResult = TemporaryMetricTable.insert {
+ it[createdAt] = metric.createdAt
+ it[value] = jsonAdapter.toJson(metric)
+ it[branch] = metric.branch
+ it[requestedTasks] = metric.requestedTasks.separateElementsWithSpace()
+ }
+ return@transaction queryResult[TemporaryMetricTable.number]
+ }
+ }
+
+ override fun getDayMetric(): Pair {
+ return db.transaction {
+ val queryResult = MetricTable.select {
+ (MetricTable.createdAt greaterEq DateTimeUtils.getDayStartMs()) and
+ (MetricTable.createdAt less DateTimeUtils.getDayEndMs()) and
+ (MetricTable.branch eq branch) and
+ (MetricTable.requestedTasks eq requestedTasks)
+ }.single()
+ return@transaction Pair(
+ jsonAdapter.fromJson(queryResult[MetricTable.value])!!, queryResult[MetricTable.number]
+ )
+ }
+ }
+
+ override fun isDayMetricExists(): Boolean {
+ return db.transaction {
+ val queryResult = MetricTable.select {
+ (MetricTable.createdAt greaterEq DateTimeUtils.getDayStartMs()) and
+ (MetricTable.createdAt less DateTimeUtils.getDayEndMs()) and
+ (MetricTable.branch eq branch) and
+ (MetricTable.requestedTasks eq requestedTasks)
+ }
+ return@transaction queryResult.count() > 0
+ }
+ }
+
+ override fun getMetrics(period: Pair): List {
+ return db.transaction {
+ val result = arrayListOf()
+ MetricTable.select {
+ (MetricTable.createdAt greaterEq period.first) and
+ (MetricTable.createdAt lessEq period.second) and
+ (MetricTable.branch eq branch) and
+ (MetricTable.requestedTasks eq requestedTasks)
+ }.orderBy(MetricTable.number, SortOrder.ASC).forEach {
+ result.add(
+ jsonAdapter.fromJson(it[MetricTable.value])!!
+ )
+ }
+ return@transaction result
+ }
+ }
+
+ override fun updateDayMetric(number: Long, metric: BuildMetric): Boolean {
+ return db.transaction {
+ val queryResult = MetricTable.update({
+ MetricTable.number eq number
+ }) {
+ it[value] = jsonAdapter.toJson(metric)
+ it[createdAt] = System.currentTimeMillis()
+ }
+ return@transaction queryResult == 1
+ }
+ }
+
+ override fun dropOutdatedTemporaryMetrics(): Boolean {
+ return db.transaction {
+ val dayMetrics = mutableListOf()
+ TemporaryMetricTable.select {
+ TemporaryMetricTable.createdAt greaterEq DateTimeUtils.getDayStartMs()
+ }.forEach {
+ dayMetrics.add(it)
+ }
+ TemporaryMetricTable.deleteAll()
+ ResetAutoIncremental.getQuery("temporary_metric")?.let {
+ exec(it)
+ }
+ if (dayMetrics.isNotEmpty()) {
+ dayMetrics.forEach { dayMetric ->
+ TemporaryMetricTable.insert {
+ it[createdAt] = dayMetric[createdAt]
+ it[value] = dayMetric[value]
+ it[branch] = dayMetric[branch]
+ it[requestedTasks] = dayMetric[requestedTasks]
+ }
+ }
+ }
+ return@transaction true
+ }
+ }
+
+ override fun dropOutdatedMetrics() {
+ return db.transaction {
+ MetricTable.deleteWhere {
+ // Delete all metrics that are created more than 1 year ago.
+ MetricTable.createdAt less (System.currentTimeMillis() - 32_140_800_000L)
+ }
+ }
+ }
+
+ override fun dropMetrics(): Boolean {
+ return db.transaction {
+ MetricTable.deleteAll()
+ ResetAutoIncremental.getQuery("metric")?.let {
+ exec(it)
+ }
+ return@transaction true
+ }
+ }
+
+ override fun getTemporaryMetrics(): List {
+ return db.transaction {
+ if (dropOutdatedTemporaryMetrics()) {
+ val metrics = arrayListOf()
+ val queryResult = TemporaryMetricTable.select {
+ (TemporaryMetricTable.branch eq branch) and
+ (TemporaryMetricTable.requestedTasks eq requestedTasks)
+ }
+ queryResult.toList().forEach {
+ jsonAdapter.fromJson(it[value])?.let { metric ->
+ metrics.add(metric)
+ }
+ }
+ return@transaction metrics
+ } else {
+ return@transaction emptyList()
+ }
+ }
+ }
+
+ override fun getSingleMetric(key: String, branch: String): String? {
+ return db.transaction {
+ val queryResult = SingleMetricTable.select {
+ (SingleMetricTable.key eq key) and (SingleMetricTable.branch eq branch)
+ }
+ if (queryResult.count() > 0) {
+ return@transaction queryResult.single()[SingleMetricTable.value]
+ }
+ return@transaction null
+ }
+ }
+
+ override fun updateSingleMetric(key: String, branch: String, value: String): Boolean {
+ return db.transaction {
+ val queryResult = SingleMetricTable.update(
+ {
+ (SingleMetricTable.key eq key) and (SingleMetricTable.branch eq branch)
+ }
+ ) {
+ it[SingleMetricTable.value] = value
+ it[createdAt] = System.currentTimeMillis()
+ }
+ return@transaction queryResult == 1
+ }
+ }
+
+ override fun saveSingleMetric(key: String, branch: String, value: String): Boolean {
+ return db.transaction {
+ SingleMetricTable.insert {
+ it[SingleMetricTable.key] = key
+ it[createdAt] = System.currentTimeMillis()
+ it[SingleMetricTable.value] = value
+ it[SingleMetricTable.branch] = branch
+ }
+ return@transaction true
+ }
+ }
+
+ override fun dropSingleMetric(key: String, branch: String): Boolean {
+ return db.transaction {
+ SingleMetricTable.deleteWhere {
+ (SingleMetricTable.key eq key) and (SingleMetricTable.branch eq branch)
+ }
+ return@transaction true
+ }
+ }
+
+ override fun dropSingleMetrics(): Boolean {
+ return db.transaction {
+ SingleMetricTable.deleteAll()
+ return@transaction true
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/database/Database.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/Database.kt
new file mode 100644
index 00000000..26658386
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/Database.kt
@@ -0,0 +1,120 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.database
+
+import io.github.janbarari.gradle.analytics.database.table.MetricTable
+import io.github.janbarari.gradle.analytics.database.table.TemporaryMetricTable
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.DatabaseConfig
+import io.github.janbarari.gradle.analytics.database.table.SingleMetricTable
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.toRealPath
+import io.github.janbarari.gradle.extension.whenNotNull
+import org.jetbrains.exposed.sql.Table
+import org.jetbrains.exposed.sql.Transaction
+import org.jetbrains.exposed.sql.SchemaUtils
+import org.jetbrains.exposed.sql.transactions.transaction
+import org.jetbrains.exposed.sql.Database
+import org.jetbrains.exposed.sql.transactions.transactionManager
+
+class Database(
+ config: DatabaseConfig,
+ private var isCI: Boolean
+) {
+
+ companion object {
+ const val DEFAULT_VARCHAR_LENGTH = 256
+ }
+
+ private lateinit var _database: Database
+ private var databaseConfig: DatabaseConnection? = null
+
+ init {
+ connect(config)
+ }
+
+ private fun connect(config: DatabaseConfig) {
+ databaseConfig = config.local
+
+ if (isCI && config.ci.isNotNull()) {
+ databaseConfig = config.ci
+ }
+
+ databaseConfig.whenNotNull {
+
+ when (databaseConfig) {
+ is MySqlDatabaseConnection -> {
+ LongTextColumnType.longTextType = LongTextColumnType.Companion.LongTextType.MEDIUMTEXT
+ connectToMysqlDatabase(databaseConfig as MySqlDatabaseConnection)
+ ResetAutoIncremental.dbType = MySqlDatabaseConnection::class.java
+ }
+ is SqliteDatabaseConnection -> {
+ LongTextColumnType.longTextType = LongTextColumnType.Companion.LongTextType.TEXT
+ connectSqliteDatabase(databaseConfig as SqliteDatabaseConnection)
+ ResetAutoIncremental.dbType = SqliteDatabaseConnection::class.java
+ }
+ }
+
+ createTables(MetricTable, TemporaryMetricTable, SingleMetricTable)
+
+ }
+ }
+
+ private fun connectToMysqlDatabase(config: MySqlDatabaseConnection) {
+ _database = Database.connect(
+ url = "jdbc:mysql://${config.host}:${config.port}/${config.name}",
+ driver = "com.mysql.cj.jdbc.Driver",
+ user = config.user,
+ password = config.password
+ )
+ }
+
+ private fun connectSqliteDatabase(config: SqliteDatabaseConnection) {
+ _database = Database.connect(
+ url = "jdbc:sqlite:${config.path!!.toRealPath()}/${config.name}.db",
+ driver = "org.sqlite.JDBC",
+ user = config.user,
+ password = config.password
+ )
+ }
+
+ /**
+ * Creates the database tables if not exist.
+ */
+ private fun createTables(vararg entities: Table) {
+ transaction {
+ SchemaUtils.createMissingTablesAndColumns(*entities, withLogs = false)
+ }
+ }
+
+ @ExcludeJacocoGenerated
+ fun transaction(statement: Transaction.() -> T): T {
+ return transaction(
+ _database.transactionManager.defaultIsolationLevel,
+ _database.transactionManager.defaultRepetitionAttempts,
+ _database,
+ statement
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/database/DatabaseConnection.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/DatabaseConnection.kt
new file mode 100644
index 00000000..39078dbe
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/DatabaseConnection.kt
@@ -0,0 +1,28 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.database
+
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+open class DatabaseConnection : java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/database/LongTextColumnType.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/LongTextColumnType.kt
new file mode 100644
index 00000000..bbfe4645
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/LongTextColumnType.kt
@@ -0,0 +1,47 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.database
+
+import org.jetbrains.exposed.sql.IColumnType
+import org.jetbrains.exposed.sql.TextColumnType
+
+/**
+ * Since the MySql database `text` column can only save a text with a maximum
+ * 65kb size. this is an extension structure to hold big text values for it.
+ */
+class LongTextColumnType : IColumnType by TextColumnType() {
+
+ companion object {
+ var longTextType: LongTextType = LongTextType.TEXT
+
+ enum class LongTextType(val value: String) {
+ TEXT("TEXT"),
+ MEDIUMTEXT("MEDIUMTEXT")
+ }
+ }
+
+ override fun sqlType(): String {
+ return longTextType.value
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/database/MySqlDatabaseConnection.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/MySqlDatabaseConnection.kt
new file mode 100644
index 00000000..8553fe50
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/MySqlDatabaseConnection.kt
@@ -0,0 +1,48 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.database
+
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+class MySqlDatabaseConnection(block: MySqlDatabaseConnection.() -> Unit): DatabaseConnection() {
+
+ companion object {
+ const val DEFAULT_MYSQL_PORT = 3306
+ }
+
+ init {
+ also(block)
+ }
+
+ lateinit var host: String
+
+ lateinit var name: String
+
+ var port: Int = DEFAULT_MYSQL_PORT
+
+ var user: String = "root"
+
+ var password: String = ""
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/database/ResetAutoIncremental.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/ResetAutoIncremental.kt
new file mode 100644
index 00000000..2aada625
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/ResetAutoIncremental.kt
@@ -0,0 +1,44 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.database
+
+/**
+ * Since tables uses auto incremental number to generate unique id, the auto-incremental
+ * won't reset after table cleared, This class helps to reset auto-incremental numbers
+ * of a table. also it will do it for both MySql and Sqlite database.
+ */
+object ResetAutoIncremental {
+ lateinit var dbType: Class
+
+ fun getQuery(tableName: String): String? {
+ if (this::dbType.isInitialized) {
+ if (dbType == MySqlDatabaseConnection::class.java) {
+ return "ALTER TABLE $tableName AUTO_INCREMENT = 0;"
+ }
+ if (dbType == SqliteDatabaseConnection::class.java) {
+ return "UPDATE SQLITE_SEQUENCE SET SEQ=0 WHERE NAME='$tableName';"
+ }
+ }
+ return null
+ }
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/database/SqliteDatabaseConnection.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/SqliteDatabaseConnection.kt
new file mode 100644
index 00000000..51b280c5
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/SqliteDatabaseConnection.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.database
+
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+class SqliteDatabaseConnection(block: SqliteDatabaseConnection.() -> Unit): DatabaseConnection() {
+
+ init {
+ also(block)
+ }
+
+ var path: String? = null
+
+ var name: String? = null
+
+ var user: String = "root"
+
+ var password: String = ""
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/database/table/MetricTable.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/table/MetricTable.kt
new file mode 100644
index 00000000..2523b634
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/table/MetricTable.kt
@@ -0,0 +1,48 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.database.table
+
+import io.github.janbarari.gradle.analytics.database.Database
+import io.github.janbarari.gradle.analytics.database.LongTextColumnType
+import org.jetbrains.exposed.sql.Table
+
+object MetricTable : Table("metric") {
+
+ /**
+ * The unique auto-generated number which represents the build-number.
+ *
+ * It also is the primary-key of the table.
+ */
+ val number = long("number").autoIncrement().uniqueIndex()
+
+ val createdAt = long("created_at")
+
+ val branch = varchar("branch", Database.DEFAULT_VARCHAR_LENGTH)
+
+ val requestedTasks = varchar("requested_tasks", Database.DEFAULT_VARCHAR_LENGTH)
+
+ val value = registerColumn("value", LongTextColumnType())
+
+ override val primaryKey = PrimaryKey(number)
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/database/table/SingleMetricTable.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/table/SingleMetricTable.kt
new file mode 100644
index 00000000..8279d073
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/table/SingleMetricTable.kt
@@ -0,0 +1,50 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.database.table
+
+import io.github.janbarari.gradle.analytics.database.Database
+import io.github.janbarari.gradle.analytics.database.LongTextColumnType
+import io.github.janbarari.gradle.analytics.database.table.TemporaryMetricTable.autoIncrement
+import io.github.janbarari.gradle.analytics.database.table.TemporaryMetricTable.uniqueIndex
+import org.jetbrains.exposed.sql.Table
+
+object SingleMetricTable : Table("single_metric") {
+
+ /**
+ * The unique auto-generated id.
+ *
+ * It also is the primary-key of the table.
+ */
+ val id = long("id").autoIncrement().uniqueIndex()
+
+ val key = varchar("key", Database.DEFAULT_VARCHAR_LENGTH)
+
+ val createdAt = long("created_at")
+
+ val branch = varchar("branch", Database.DEFAULT_VARCHAR_LENGTH)
+
+ val value = registerColumn("value", LongTextColumnType())
+
+ override val primaryKey = PrimaryKey(id)
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/database/table/TemporaryMetricTable.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/table/TemporaryMetricTable.kt
new file mode 100644
index 00000000..377d6946
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/database/table/TemporaryMetricTable.kt
@@ -0,0 +1,48 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.database.table
+
+import io.github.janbarari.gradle.analytics.database.Database
+import io.github.janbarari.gradle.analytics.database.LongTextColumnType
+import org.jetbrains.exposed.sql.Table
+
+object TemporaryMetricTable : Table("temporary_metric") {
+
+ /**
+ * The unique auto-generated number which represents the build-number.
+ *
+ * It also is the primary-key of the table.
+ */
+ val number = long("number").autoIncrement().uniqueIndex()
+
+ val createdAt = long("created_at")
+
+ val branch = varchar("branch", Database.DEFAULT_VARCHAR_LENGTH)
+
+ val requestedTasks = varchar("requested_tasks", Database.DEFAULT_VARCHAR_LENGTH)
+
+ val value = registerColumn("value", LongTextColumnType())
+
+ override val primaryKey = PrimaryKey(number)
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/BuildInfo.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/BuildInfo.kt
new file mode 100644
index 00000000..589eab91
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/BuildInfo.kt
@@ -0,0 +1,184 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model
+
+import io.github.janbarari.gradle.extension.whenNotNull
+import org.gradle.tooling.Failure
+import java.time.Duration
+
+data class BuildInfo(
+ val createdAt: Long,
+ val startedAt: Long,
+ val initializedAt: Long,
+ val configuredAt: Long,
+ var dependenciesResolveInfo: Collection,
+ val executedTasks: List,
+ val finishedAt: Long,
+ val branch: String,
+ val gitHeadCommitHash: String,
+ val requestedTasks: List,
+ val isSuccessful: Boolean,
+ val failure: List? = null
+) : java.io.Serializable {
+
+ init {
+ // Replace pass-by-reference to pass-by-value, cause the collection will be reset after creation of BuildInfo.
+ dependenciesResolveInfo = dependenciesResolveInfo.toList()
+ }
+
+ /**
+ * Returns the total build duration.
+ */
+ fun getTotalDuration(): Duration {
+ if (finishedAt < startedAt) return Duration.ofMillis(0)
+ return Duration.ofMillis(finishedAt - startedAt)
+ }
+
+ /**
+ * Returns the build initialization process duration.
+ */
+ fun getInitializationDuration(): Duration {
+ if (initializedAt < startedAt) return Duration.ofMillis(0)
+ return Duration.ofMillis(initializedAt - startedAt)
+ }
+
+ /**
+ * Returns the build configuration process duration.
+ */
+ fun getConfigurationDuration(): Duration {
+ if (configuredAt < initializedAt) return Duration.ofMillis(0)
+ return Duration.ofMillis(configuredAt - initializedAt)
+ }
+
+ /**
+ * Returns the build execution process duration.
+ */
+ fun getExecutionDuration(): Duration {
+ if (finishedAt < configuredAt) return Duration.ofMillis(0)
+ return Duration.ofMillis(finishedAt - configuredAt)
+ }
+
+ /**
+ * Returns the total dependencies resolve duration.
+ */
+ fun getTotalDependenciesResolveDuration(): Duration {
+ var result = 0L
+ val iterator = dependenciesResolveInfo.iterator()
+ while (iterator.hasNext()) {
+ val info = iterator.next()
+ result += info.getDuration()
+ }
+ return Duration.ofMillis(result)
+ }
+
+ /**
+ * Calculates the cumulative parallel execution duration in milliseconds.
+ */
+ fun calculateParallelExecutionByMillis(): Long {
+ return executedTasks.sumOf { it.getDurationInMillis() }
+ }
+
+ /**
+ * Gradle executes the project tasks in parallel to use maximum performance of
+ * the system resources, Which means by adding the task's duration together,
+ * We calculated the serial duration. to calculate the non-parallel
+ * duration(real-life duration) we need to ignore those tasks that are executed at
+ * the same time or covered times by another task.
+ */
+ fun calculateNonParallelExecutionInMillis(executedTasks: List = this.executedTasks): Long {
+ fun checkIfCanMerge(
+ parallelTask: TaskInfo,
+ nonParallelTask: Map.Entry>,
+ nonParallelTasks: HashMap>
+ ) {
+ if (parallelTask.startedAt <= nonParallelTask.value.second &&
+ parallelTask.finishedAt >= nonParallelTask.value.second) {
+
+ var start = nonParallelTask.value.first
+ var end = nonParallelTask.value.second
+
+ if (parallelTask.startedAt < nonParallelTask.value.first)
+ start = parallelTask.startedAt
+
+ if (parallelTask.finishedAt > nonParallelTask.value.second)
+ end = parallelTask.finishedAt
+ nonParallelTasks[nonParallelTask.key] = Pair(start, end)
+ }
+ }
+
+ val nonParallelDurations = hashMapOf>()
+
+ val executedTaskIterator = executedTasks
+ .sortedBy { task -> task.startedAt }
+ .iterator()
+
+ while (executedTaskIterator.hasNext()) {
+ val executedTask = executedTaskIterator.next()
+ if (nonParallelDurations.isEmpty()) {
+ nonParallelDurations[nonParallelDurations.size] = Pair(executedTask.startedAt, executedTask.finishedAt)
+ continue
+ }
+
+ var tempTask: Pair? = null
+ val nonParallelTasksIterator = nonParallelDurations.iterator()
+ while (nonParallelTasksIterator.hasNext()) {
+ val nonParallelTask = nonParallelTasksIterator.next()
+
+ checkIfCanMerge(executedTask, nonParallelTask, nonParallelDurations)
+
+ if (executedTask.startedAt > nonParallelTask.value.first &&
+ executedTask.finishedAt > nonParallelTask.value.second &&
+ executedTask.finishedAt > executedTask.startedAt
+ ) {
+ tempTask = Pair(executedTask.startedAt, executedTask.finishedAt)
+ }
+ }
+
+ tempTask.whenNotNull {
+ val iterator = nonParallelDurations.iterator()
+ while (iterator.hasNext()) {
+ val nonParallelTask = iterator.next()
+ if (nonParallelTask.value.second in first..second) {
+ var start = nonParallelTask.value.first
+ var end = nonParallelTask.value.second
+ if (first < nonParallelTask.value.first) {
+ start = first
+ }
+ if (second > nonParallelTask.value.second) {
+ end = second
+ }
+ nonParallelDurations[nonParallelTask.key] = Pair(start, end)
+ }
+ }
+
+ val biggestNonParallelTaskEnd = nonParallelDurations.toList().maxByOrNull { it.second.second }!!.second.second
+ if (first > biggestNonParallelTaskEnd) {
+ nonParallelDurations[nonParallelDurations.size] = this
+ }
+ }
+ }
+
+ return nonParallelDurations.toList().sumOf { (it.second.second - it.second.first) }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/ChartPoint.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/ChartPoint.kt
new file mode 100644
index 00000000..c4de603a
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/ChartPoint.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ChartPoint(
+ @Json(name = "value")
+ val value: Long,
+ @Json(name = "description")
+ val description: String
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/Dependency.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/Dependency.kt
new file mode 100644
index 00000000..e9d44912
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/Dependency.kt
@@ -0,0 +1,70 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import org.gradle.api.Project
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class Dependency(
+ @Json(name = "name")
+ val name: String,
+ @Json(name = "module_name")
+ val moduleName: String,
+ @Json(name = "module_group")
+ val moduleGroup: String,
+ @Json(name = "module_version")
+ val moduleVersion: String,
+ @Json(name = "size_by_kb")
+ val sizeByKb: Long
+): java.io.Serializable {
+
+ companion object {
+
+ fun Project.getThirdPartyDependencies(): List {
+ return subprojects.flatMap { project ->
+ project.configurations.filter {
+ it.isCanBeResolved && it.name.contains("compileClassPath", ignoreCase = true)
+ }.flatMap { configuration ->
+ configuration.resolvedConfiguration.firstLevelModuleDependencies.filter { resolvedDependency ->
+ !resolvedDependency.moduleVersion.equals("unspecified", true)
+ }.map { it }
+ }
+ }.toSet()
+ .map {
+ Dependency(
+ name = it.name,
+ moduleName = it.moduleName,
+ moduleGroup = it.moduleGroup,
+ moduleVersion = it.moduleVersion,
+ sizeByKb = it.moduleArtifacts.sumOf { artifact -> artifact.file.length() / 1024L }
+ )
+ }
+ }
+
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/DependencyResolveInfo.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/DependencyResolveInfo.kt
new file mode 100644
index 00000000..e0c2ca9a
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/DependencyResolveInfo.kt
@@ -0,0 +1,46 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class DependencyResolveInfo(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "started_at")
+ val startedAt: Long,
+ @Json(name = "finished_at")
+ var finishedAt: Long = 0L
+) : java.io.Serializable {
+
+ /**
+ * Returns the resolve duration in milliseconds.
+ */
+ fun getDuration(): Long {
+ if (finishedAt < startedAt) return 0L
+ return finishedAt - startedAt
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/Module.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/Module.kt
new file mode 100644
index 00000000..4d7422c1
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/Module.kt
@@ -0,0 +1,46 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import org.gradle.api.Project
+
+@JsonClass(generateAdapter = true)
+data class Module(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "absoluteDir")
+ val absoluteDir: String
+): java.io.Serializable {
+
+ companion object {
+ fun Project.toModule(): Module {
+ return Module(
+ path = path,
+ absoluteDir = projectDir.absolutePath
+ )
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/ModuleDependency.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/ModuleDependency.kt
new file mode 100644
index 00000000..37d8dcf8
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/ModuleDependency.kt
@@ -0,0 +1,39 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleDependency(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "configuration")
+ val configuration: String,
+ @Json(name = "dependency")
+ val dependency: String
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/ModulesDependencyGraph.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/ModulesDependencyGraph.kt
new file mode 100644
index 00000000..43b61924
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/ModulesDependencyGraph.kt
@@ -0,0 +1,35 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesDependencyGraph(
+ @Json(name = "dependencies")
+ val dependencies: List
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/TaskInfo.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/TaskInfo.kt
new file mode 100644
index 00000000..55641d99
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/TaskInfo.kt
@@ -0,0 +1,79 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import org.gradle.tooling.Failure
+import org.gradle.tooling.events.OperationDescriptor
+
+@JsonClass(generateAdapter = true)
+data class TaskInfo(
+ @Json(name = "started_at")
+ val startedAt: Long,
+ @Json(name = "finished_at")
+ val finishedAt: Long,
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "display_name")
+ val displayName: String,
+ @Json(name = "name")
+ val name: String,
+ @Json(name = "is_successful")
+ val isSuccessful: Boolean,
+ @Json(name = "failures")
+ val failures: List?,
+ @Json(name = "dependencies")
+ val dependencies: List?,
+ @Json(name = "is_incremental")
+ val isIncremental: Boolean,
+ @Json(name = "is_from_cache")
+ val isFromCache: Boolean,
+ @Json(name = "is_up_to_date")
+ val isUpToDate: Boolean,
+ @Json(name = "is_skipped")
+ val isSkipped: Boolean,
+ @Json(name = "execution_reasons")
+ val executionReasons: List?
+) : java.io.Serializable {
+
+ /**
+ * Returns the task execution duration in milliseconds.
+ */
+ fun getDurationInMillis(): Long {
+ if (finishedAt < startedAt) return 0L
+ return finishedAt - startedAt
+ }
+
+ /**
+ * Returns the task module name.
+ */
+ fun getModule(): String {
+ val module = path.split(":")
+ return if (module.size > 2) module.toList()
+ .dropLast(1)
+ .joinToString(separator = ":")
+ else "no_module"
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/TimespanPoint.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/TimespanPoint.kt
new file mode 100644
index 00000000..ecc0aae2
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/TimespanPoint.kt
@@ -0,0 +1,48 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.utils.DateTimeUtils
+
+@JsonClass(generateAdapter = true)
+data class TimespanPoint(
+ @Json(name = "value")
+ val value: Long,
+ @Json(name = "from")
+ val from: Long,
+ @Json(name = "to")
+ val to: Long? = null
+): io.github.janbarari.gradle.core.Triple(value, from, to) {
+
+ fun getTimespanString(): String {
+ return if (to.isNull()) {
+ DateTimeUtils.format(from, "dd/MM")
+ } else {
+ DateTimeUtils.format(from, "dd/MM") + "-" + DateTimeUtils.format(to!!, "dd/MM")
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/BuildMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/BuildMetric.kt
new file mode 100644
index 00000000..d8def289
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/BuildMetric.kt
@@ -0,0 +1,103 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class BuildMetric(
+
+ @Json(name = "branch")
+ var branch: String,
+
+ @Json(name = "requested_tasks")
+ var requestedTasks: List,
+
+ @Json(name = "created_at")
+ var createdAt: Long,
+
+ @Json(name = "git_head_commit_hash")
+ var gitHeadCommitHash: String,
+
+ @Json(name = "initialization_process_metric")
+ var initializationProcessMetric: InitializationProcessMetric? = null,
+
+ @Json(name = "configuration_process_metric")
+ var configurationProcessMetric: ConfigurationProcessMetric? = null,
+
+ @Json(name = "execution_process_metric")
+ var executionProcessMetric: ExecutionProcessMetric? = null,
+
+ @Json(name = "overall_build_process_metric")
+ var overallBuildProcessMetric: OverallBuildProcessMetric? = null,
+
+ @Json(name = "modules_source_count_metric")
+ var modulesSourceCountMetric: ModulesSourceCountMetric? = null,
+
+ @Json(name = "modules_method_count_metric")
+ var modulesMethodCountMetric: ModulesMethodCountMetric? = null,
+
+ @Json(name = "cache_hit_metric")
+ var cacheHitMetric: CacheHitMetric? = null,
+
+ @Json(name = "success_build_rate_metric")
+ var successBuildRateMetric: SuccessBuildRateMetric? = null,
+
+ @Json(name = "dependency_resolve_process_metric")
+ var dependencyResolveProcessMetric: DependencyResolveProcessMetric? = null,
+
+ @Json(name = "parallel_execution_rate_metric")
+ var parallelExecutionRateMetric: ParallelExecutionRateMetric? = null,
+
+ @Json(name = "modules_execution_process_metric")
+ var modulesExecutionProcessMetric: ModulesExecutionProcessMetric? = null,
+
+ @Json(name = "modules_dependency_graph_metric")
+ var modulesDependencyGraphMetric: ModulesDependencyGraphMetric? = null,
+
+ @Json(name = "modules_build_heatmap_metric")
+ var modulesBuildHeatmap: ModulesBuildHeatmapMetric? = null,
+
+ @Json(name = "dependency_details_metric")
+ var dependencyDetailsMetric: DependencyDetailsMetric? = null,
+
+ @Json(name = "non_cacheable_tasks_metric")
+ var nonCacheableTasksMetric: NonCacheableTasksMetric? = null,
+
+ @Json(name = "modules_source_size_metric")
+ var modulesSourceSizeMetric: ModulesSourceSizeMetric? = null,
+
+ @Json(name = "modules_crash_count_metric")
+ var modulesCrashCountMetric: ModulesCrashCountMetric? = null,
+
+): java.io.Serializable {
+
+ // Exclude from build metric json to avoid save in metric table. Regarding the metric
+ // size and usability, this metric should be saved in `single_metric` table.
+ @Transient
+ var modulesTimelineMetric: ModulesTimelineMetric? = null
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/CacheHitMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/CacheHitMetric.kt
new file mode 100644
index 00000000..8e840520
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/CacheHitMetric.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class CacheHitMetric(
+ @Json(name = "rate")
+ val rate: Long,
+ @Json(name = "modules")
+ val modules: List
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ConfigurationProcessMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ConfigurationProcessMetric.kt
new file mode 100644
index 00000000..27d6df13
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ConfigurationProcessMetric.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ConfigurationProcessMetric(
+ @Json(name = "median")
+ var median: Long = 0L,
+ @Json(name = "mean")
+ var mean: Long = 0L
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/DependencyDetailsMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/DependencyDetailsMetric.kt
new file mode 100644
index 00000000..06f287f8
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/DependencyDetailsMetric.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.Dependency
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class DependencyDetailsMetric(
+ @Json(name = "dependencies")
+ val dependencies: List
+): java.io.Serializable
+
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/DependencyResolveProcessMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/DependencyResolveProcessMetric.kt
new file mode 100644
index 00000000..15325400
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/DependencyResolveProcessMetric.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class DependencyResolveProcessMetric(
+ @Json(name = "median")
+ var median: Long = 0L,
+ @Json(name = "mean")
+ var mean: Long = 0L
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ExecutionProcessMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ExecutionProcessMetric.kt
new file mode 100644
index 00000000..14e4b555
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ExecutionProcessMetric.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ExecutionProcessMetric(
+ @Json(name = "median")
+ var median: Long = 0L,
+ @Json(name = "mean")
+ var mean: Long = 0L
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/InitializationProcessMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/InitializationProcessMetric.kt
new file mode 100644
index 00000000..07ca8830
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/InitializationProcessMetric.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class InitializationProcessMetric(
+ @Json(name = "median")
+ var median: Long = 0L,
+ @Json(name = "mean")
+ var mean: Long = 0L
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleBuildHeatmap.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleBuildHeatmap.kt
new file mode 100644
index 00000000..43693df8
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleBuildHeatmap.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleBuildHeatmap(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "dependant_modules_count")
+ val dependantModulesCount: Int
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleCacheHit.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleCacheHit.kt
new file mode 100644
index 00000000..d8cceb80
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleCacheHit.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleCacheHit(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "rate")
+ var rate: Long
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleExecutionProcess.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleExecutionProcess.kt
new file mode 100644
index 00000000..556318bb
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleExecutionProcess.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleExecutionProcess(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "median")
+ val medianExecInMillis: Long,
+ @Json(name = "median_parallel")
+ val medianParallelExecInMillis: Long,
+ @Json(name = "parallel_rate")
+ val parallelRate: Float,
+ @Json(name = "coverage")
+ val coverageRate: Float
+) : java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleMethodCount.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleMethodCount.kt
new file mode 100644
index 00000000..e918ebd5
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleMethodCount.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleMethodCount(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "value")
+ val value: Int
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleSourceCount.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleSourceCount.kt
new file mode 100644
index 00000000..3bb6d281
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleSourceCount.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleSourceCount(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "value")
+ val value: Int
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleTimeline.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleTimeline.kt
new file mode 100644
index 00000000..50e1e246
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModuleTimeline.kt
@@ -0,0 +1,52 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleTimeline(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "timelines")
+ val timelines: List
+) {
+
+ @ExcludeJacocoGenerated
+ @JsonClass(generateAdapter = true)
+ data class Timeline(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "start")
+ val start: Long,
+ @Json(name = "end")
+ val end: Long,
+ @Json(name = "is_cached")
+ val isCached: Boolean
+ )
+
+}
+
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesBuildHeatmapMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesBuildHeatmapMetric.kt
new file mode 100644
index 00000000..fee73086
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesBuildHeatmapMetric.kt
@@ -0,0 +1,35 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesBuildHeatmapMetric(
+ @Json(name = "modules")
+ val modules: List
+): java.io.Serializable
+
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesCrashCountMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesCrashCountMetric.kt
new file mode 100644
index 00000000..95cf2565
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesCrashCountMetric.kt
@@ -0,0 +1,45 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesCrashCountMetric(
+ @Json(name = "modules")
+ val modules: List
+): java.io.Serializable {
+
+ @ExcludeJacocoGenerated
+ @JsonClass(generateAdapter = true)
+ data class ModuleCrash(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "crash_count")
+ val totalCrashes: Long,
+ ): java.io.Serializable
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesDependencyGraphMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesDependencyGraphMetric.kt
new file mode 100644
index 00000000..453442f9
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesDependencyGraphMetric.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ModuleDependency
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesDependencyGraphMetric(
+ @Json(name = "dependencies")
+ var dependencies: List
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesExecutionProcessMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesExecutionProcessMetric.kt
new file mode 100644
index 00000000..1a7e87c1
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesExecutionProcessMetric.kt
@@ -0,0 +1,34 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesExecutionProcessMetric(
+ @Json(name = "modules")
+ var modules: List
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesMethodCountMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesMethodCountMetric.kt
new file mode 100644
index 00000000..a464674c
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesMethodCountMetric.kt
@@ -0,0 +1,35 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesMethodCountMetric(
+ @Json(name = "modules")
+ val modules: List
+): java.io.Serializable
+
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesSourceCountMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesSourceCountMetric.kt
new file mode 100644
index 00000000..cbb9b913
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesSourceCountMetric.kt
@@ -0,0 +1,35 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesSourceCountMetric(
+ @Json(name = "modules")
+ val modules: List
+): java.io.Serializable
+
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesSourceSizeMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesSourceSizeMetric.kt
new file mode 100644
index 00000000..51351c5c
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesSourceSizeMetric.kt
@@ -0,0 +1,46 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesSourceSizeMetric(
+ @Json(name = "modules")
+ val modules: List
+): java.io.Serializable {
+
+ @ExcludeJacocoGenerated
+ @JsonClass(generateAdapter = true)
+ data class ModuleSourceSize(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "size_by_kb")
+ val sizeInKb: Long
+ ): java.io.Serializable
+
+}
+
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesTimelineMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesTimelineMetric.kt
new file mode 100644
index 00000000..505b1aaa
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ModulesTimelineMetric.kt
@@ -0,0 +1,40 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesTimelineMetric(
+ @Json(name = "start")
+ val start: Long,
+ @Json(name = "end")
+ val end: Long,
+ @Json(name = "modules")
+ val modules: List,
+ @Json(name = "created_at")
+ val createdAt: Long,
+)
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/NonCacheableTasksMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/NonCacheableTasksMetric.kt
new file mode 100644
index 00000000..abe1063e
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/NonCacheableTasksMetric.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class NonCacheableTasksMetric(
+ val tasks: List
+): Serializable {
+
+ @ExcludeJacocoGenerated
+ @JsonClass(generateAdapter = true)
+ data class NonCacheableTask(
+ val path: String,
+ var avgExecutionDurationInMillis: Long
+ ): Serializable
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/OverallBuildProcessMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/OverallBuildProcessMetric.kt
new file mode 100644
index 00000000..fdc26d4d
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/OverallBuildProcessMetric.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class OverallBuildProcessMetric(
+ @Json(name = "median")
+ var median: Long = 0L,
+ @Json(name = "mean")
+ var mean: Long = 0L
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ParallelExecutionRateMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ParallelExecutionRateMetric.kt
new file mode 100644
index 00000000..130c6295
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/ParallelExecutionRateMetric.kt
@@ -0,0 +1,34 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ParallelExecutionRateMetric(
+ @Json(name = "median_rate")
+ var medianRate: Long = 0L
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/SuccessBuildRateMetric.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/SuccessBuildRateMetric.kt
new file mode 100644
index 00000000..73da372c
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/metric/SuccessBuildRateMetric.kt
@@ -0,0 +1,40 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.metric
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class SuccessBuildRateMetric(
+ @Json(name = "median_rate")
+ var medianRate: Float = 0f,
+ @Json(name = "mean_rate")
+ var meanRate: Float = 0f,
+ @Json(name = "successes")
+ var successes: Int = 0,
+ @Json(name = "fails")
+ var fails: Int = 0
+) : java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/os/HardwareInfo.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/os/HardwareInfo.kt
new file mode 100644
index 00000000..98319192
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/os/HardwareInfo.kt
@@ -0,0 +1,31 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.os
+
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+data class HardwareInfo(
+ val availableMemory: Long,
+ val maximumMemoryCapacity: Long
+) : java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/os/OsInfo.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/os/OsInfo.kt
new file mode 100644
index 00000000..14d87385
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/os/OsInfo.kt
@@ -0,0 +1,30 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.os
+
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+data class OsInfo(
+ val name: String
+) : java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/BuildStatusReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/BuildStatusReport.kt
new file mode 100644
index 00000000..7fea9261
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/BuildStatusReport.kt
@@ -0,0 +1,59 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class BuildStatusReport(
+ @Json(name = "cumulative_overall_build_process_by_seconds")
+ val cumulativeOverallBuildProcessBySeconds: Long,
+ @Json(name = "avg_overall_build_process_by_seconds")
+ val avgOverallBuildProcessBySeconds: Long,
+ @Json(name = "total_build_process_count")
+ val totalBuildProcessCount: Int,
+ @Json(name = "total_project_modules_count")
+ val totalProjectModulesCount: Int,
+ @Json(name = "cumulative_parallel_execution_by_seconds")
+ val cumulativeParallelExecutionBySeconds: Long,
+ @Json(name = "avg_parallel_execution_rate")
+ val avgParallelExecutionRate: Float,
+ @Json(name = "total_succeed_build_count")
+ val totalSucceedBuildCount: Int,
+ @Json(name = "total_failed_build_count")
+ val totalFailedBuildCount: Int,
+ @Json(name = "avg_cache_hit_rate")
+ val avgCacheHitRate: Float,
+ @Json(name = "cumulative_dependency_resolve_by_seconds")
+ val cumulativeDependencyResolveBySeconds: Long,
+ @Json(name = "avg_initialization_process_by_millis")
+ val avgInitializationProcessByMillis: Long,
+ @Json(name = "avg_configuration_process_by_millis")
+ val avgConfigurationProcessByMillis: Long,
+ @Json(name = "avg_execution_process_by_seconds")
+ val avgExecutionProcessBySeconds: Long
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/CacheHitReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/CacheHitReport.kt
new file mode 100644
index 00000000..18e2fa80
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/CacheHitReport.kt
@@ -0,0 +1,43 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ChartPoint
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class CacheHitReport(
+ @Json(name = "modules")
+ val modules: List,
+ @Json(name = "overall_mean_values")
+ val overallMeanValues: List,
+ @Json(name = "overall_rate")
+ val overallRate: Long,
+ @Json(name = "overall_diff_rate")
+ val overallDiffRate: Float? = null
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ConfigurationProcessReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ConfigurationProcessReport.kt
new file mode 100644
index 00000000..f4ca4ec0
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ConfigurationProcessReport.kt
@@ -0,0 +1,37 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ConfigurationProcessReport(
+ @Json(name = "median_values")
+ val medianValues: List,
+ @Json(name = "mean_values")
+ val meanValues: List,
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/DependencyDetailsReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/DependencyDetailsReport.kt
new file mode 100644
index 00000000..dd522e14
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/DependencyDetailsReport.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.Dependency
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class DependencyDetailsReport(
+ @Json(name = "dependencies")
+ val dependencies: List,
+ @Json(name = "cumulative_dependencies_size_by_kb")
+ val cumulativeDependenciesSizeByKb: Long
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/DependencyResolveProcessReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/DependencyResolveProcessReport.kt
new file mode 100644
index 00000000..bdeccebf
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/DependencyResolveProcessReport.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ChartPoint
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class DependencyResolveProcessReport(
+ @Json(name = "median_values")
+ val medianValues: List,
+ @Json(name = "mean_values")
+ val meanValues: List,
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ExecutionProcessReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ExecutionProcessReport.kt
new file mode 100644
index 00000000..b6dae584
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ExecutionProcessReport.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ChartPoint
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ExecutionProcessReport(
+ @Json(name = "median_values")
+ val medianValues: List,
+ @Json(name = "mean_values")
+ val meanValues: List
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/InitializationProcessReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/InitializationProcessReport.kt
new file mode 100644
index 00000000..e5dc4f90
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/InitializationProcessReport.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ChartPoint
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class InitializationProcessReport(
+ @Json(name = "median_values")
+ val medianValues: List,
+ @Json(name = "mean_values")
+ val meanValues: List
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleBuildHeatmap.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleBuildHeatmap.kt
new file mode 100644
index 00000000..1ff6c64c
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleBuildHeatmap.kt
@@ -0,0 +1,40 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleBuildHeatmap(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "dependant_modules_count")
+ val dependantModulesCount: Int,
+ @Json(name = "avg_median_cache_hit")
+ val avgMedianCacheHit: Long,
+ @Json(name = "total_build_count")
+ val totalBuildCount: Int
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleCacheHit.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleCacheHit.kt
new file mode 100644
index 00000000..c93c22b1
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleCacheHit.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ChartPoint
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleCacheHit(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "rate")
+ val rate: Long,
+ @Json(name = "diff_rate")
+ val diffRate: Float? = null,
+ @Json(name = "mean_values")
+ val meanValues: List
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleExecutionProcess.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleExecutionProcess.kt
new file mode 100644
index 00000000..43472fbb
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleExecutionProcess.kt
@@ -0,0 +1,47 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleExecutionProcess(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "avg_median_duration")
+ val avgMedianExecInMillis: Long,
+ @Json(name = "avg_median_parallel_duration")
+ val avgMedianParallelExecInMillis: Long,
+ @Json(name = "avg_median_parallel_rate")
+ val avgMedianParallelRate: Float,
+ @Json(name = "avg_median_coverage")
+ val avgMedianCoverageRate: Float,
+ @Json(name = "avg_median_durations")
+ val avgMedianExecs: List,
+ @Json(name = "diff_rate")
+ val diffRate: Float?
+) : java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleMethodCount.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleMethodCount.kt
new file mode 100644
index 00000000..92f5658b
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleMethodCount.kt
@@ -0,0 +1,40 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleMethodCount(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "value")
+ val value: Int,
+ @Json(name = "coverage")
+ val coverageRate: Float,
+ @Json(name = "diff_rate")
+ val diffRate: Float? = null
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleSourceCount.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleSourceCount.kt
new file mode 100644
index 00000000..ed242a7b
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModuleSourceCount.kt
@@ -0,0 +1,40 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModuleSourceCount(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "value")
+ val value: Int,
+ @Json(name = "coverage")
+ val coverageRate: Float,
+ @Json(name = "diff_rate")
+ val diffRate: Float? = null
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesBuildHeatmapReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesBuildHeatmapReport.kt
new file mode 100644
index 00000000..16e3b568
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesBuildHeatmapReport.kt
@@ -0,0 +1,35 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesBuildHeatmapReport(
+ @Json(name = "modules")
+ val modules: List
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesCrashCountReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesCrashCountReport.kt
new file mode 100644
index 00000000..ed2ae5c0
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesCrashCountReport.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesCrashCountMetric
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesCrashCountReport(
+ @Json(name = "modules")
+ val modules: List
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesDependencyGraphReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesDependencyGraphReport.kt
new file mode 100644
index 00000000..d3aaabcd
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesDependencyGraphReport.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ModuleDependency
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesDependencyGraphReport(
+ @Json(name = "dependencies")
+ var dependencies: List
+) : Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesExecutionProcessReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesExecutionProcessReport.kt
new file mode 100644
index 00000000..a2878b80
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesExecutionProcessReport.kt
@@ -0,0 +1,35 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ChartPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesExecutionProcessReport(
+ @Json(name = "modules")
+ val modules: List
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesMethodCountReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesMethodCountReport.kt
new file mode 100644
index 00000000..455f0b58
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesMethodCountReport.kt
@@ -0,0 +1,39 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesMethodCountReport(
+ @Json(name = "values")
+ val values: List,
+ @Json(name = "total_method_count")
+ val totalMethodCount: Int,
+ @Json(name = "total_diff_rate")
+ val totalDiffRate: Float? = null
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesSourceCountReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesSourceCountReport.kt
new file mode 100644
index 00000000..a1c62520
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesSourceCountReport.kt
@@ -0,0 +1,39 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesSourceCountReport(
+ @Json(name = "values")
+ val values: List,
+ @Json(name = "total_source_count")
+ val totalSourceCount: Int,
+ @Json(name = "total_diff_rate")
+ val totalDiffRate: Float? = null
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesSourceSizeReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesSourceSizeReport.kt
new file mode 100644
index 00000000..95a7cbc9
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesSourceSizeReport.kt
@@ -0,0 +1,54 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesSourceSizeReport(
+ @Json(name = "values")
+ val values: List,
+ @Json(name = "total_source_size_by_kb")
+ val totalSourceSizeInKb: Long,
+ @Json(name = "total_diff_rate")
+ val totalDiffRate: Float? = null
+): Serializable {
+
+ @ExcludeJacocoGenerated
+ @JsonClass(generateAdapter = true)
+ data class ModuleSourceSize(
+ @Json(name = "path")
+ val path: String,
+ @Json(name = "size_by_kb")
+ val sizeInKb: Long,
+ @Json(name = "coverage")
+ val coverageRate: Float,
+ @Json(name = "diff_rate")
+ val diffRate: Float? = null
+ ): Serializable
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesTimelineReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesTimelineReport.kt
new file mode 100644
index 00000000..fa32f622
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ModulesTimelineReport.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModuleTimeline
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ModulesTimelineReport(
+ @Json(name = "start")
+ val start: Long,
+ @Json(name = "end")
+ val end: Long,
+ @Json(name = "modules")
+ val modules: List,
+ @Json(name = "created_at")
+ val createdAt: Long
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/NonCacheableTasksReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/NonCacheableTasksReport.kt
new file mode 100644
index 00000000..4938ddf7
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/NonCacheableTasksReport.kt
@@ -0,0 +1,36 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.metric.NonCacheableTasksMetric
+import java.io.Serializable
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class NonCacheableTasksReport(
+ @Json(name = "tasks")
+ val tasks: List
+): Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/OverallBuildProcessReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/OverallBuildProcessReport.kt
new file mode 100644
index 00000000..4feae285
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/OverallBuildProcessReport.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ChartPoint
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class OverallBuildProcessReport(
+ @Json(name = "median_values")
+ val medianValues: List,
+ @Json(name = "mean_values")
+ val meanValues: List
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ParallelExecutionRateReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ParallelExecutionRateReport.kt
new file mode 100644
index 00000000..991e0008
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/ParallelExecutionRateReport.kt
@@ -0,0 +1,35 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class ParallelExecutionRateReport(
+ @Json(name = "median_values")
+ val medianValues: List
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/Report.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/Report.kt
new file mode 100644
index 00000000..d9601982
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/Report.kt
@@ -0,0 +1,105 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonAdapter
+import com.squareup.moshi.JsonClass
+import com.squareup.moshi.Moshi
+
+@JsonClass(generateAdapter = true)
+data class Report(
+
+ @Json(name = "branch")
+ val branch: String,
+
+ @Json(name = "requested_tasks")
+ val requestedTasks: String,
+
+ @Json(name = "initialization_process_report")
+ var initializationProcessReport: InitializationProcessReport? = null,
+
+ @Json(name = "configuration_process_report")
+ var configurationProcessReport: ConfigurationProcessReport? = null,
+
+ @Json(name = "execution_process_report")
+ var executionProcessReport: ExecutionProcessReport? = null,
+
+ @Json(name = "overall_build_process_report")
+ var overallBuildProcessReport: OverallBuildProcessReport? = null,
+
+ @Json(name = "modules_source_count_report")
+ var modulesSourceCountReport: ModulesSourceCountReport? = null,
+
+ @Json(name = "modules_method_count_report")
+ var modulesMethodCountReport: ModulesMethodCountReport? = null,
+
+ @Json(name = "cache_hit_report")
+ var cacheHitReport: CacheHitReport? = null,
+
+ @Json(name = "success_build_rate_report")
+ var successBuildRateReport: SuccessBuildRateReport? = null,
+
+ @Json(name = "dependency_resolve_process_report")
+ var dependencyResolveProcessReport: DependencyResolveProcessReport? = null,
+
+ @Json(name = "parallel_execution_rate_report")
+ var parallelExecutionRateReport: ParallelExecutionRateReport? = null,
+
+ @Json(name = "modules_execution_process_report")
+ var modulesExecutionProcessReport: ModulesExecutionProcessReport? = null,
+
+ @Json(name = "modules_dependency_graph_report")
+ var modulesDependencyGraphReport: ModulesDependencyGraphReport? = null,
+
+ @Json(name = "modules_timeline_report")
+ var modulesTimelineReport: ModulesTimelineReport? = null,
+
+ @Json(name = "build_status_report")
+ var buildStatusReport: BuildStatusReport? = null,
+
+ @Json(name = "modules_build_heatmap_report")
+ var modulesBuildHeatmapReport: ModulesBuildHeatmapReport? = null,
+
+ @Json(name = "dependency_details_report")
+ var dependencyDetailsReport: DependencyDetailsReport? = null,
+
+ @Json(name = "non_cacheable_tasks_report")
+ var nonCacheableTasksReport: NonCacheableTasksReport? = null,
+
+ @Json(name = "modules_source_size_report")
+ var modulesSourceSizeReport: ModulesSourceSizeReport? = null,
+
+ @Json(name = "modules_crash_count_report")
+ var modulesCrashCountReport: ModulesCrashCountReport? = null,
+
+) : java.io.Serializable {
+
+ fun toJson(): String {
+ val moshi: Moshi = Moshi.Builder().build()
+ val jsonAdapter: JsonAdapter = ReportJsonAdapter(moshi)
+ return jsonAdapter.toJson(this)
+ }
+
+}
+
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/SuccessBuildRateReport.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/SuccessBuildRateReport.kt
new file mode 100644
index 00000000..6ec7ccf8
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/model/report/SuccessBuildRateReport.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.model.report
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import io.github.janbarari.gradle.ExcludeJacocoGenerated
+import io.github.janbarari.gradle.analytics.domain.model.ChartPoint
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+
+@ExcludeJacocoGenerated
+@JsonClass(generateAdapter = true)
+data class SuccessBuildRateReport(
+ @Json(name = "median_values")
+ val medianValues: List,
+ @Json(name = "mean_values")
+ val meanValues: List
+): java.io.Serializable
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/repository/DatabaseRepository.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/repository/DatabaseRepository.kt
new file mode 100644
index 00000000..c124a8c0
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/repository/DatabaseRepository.kt
@@ -0,0 +1,48 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.repository
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+
+interface DatabaseRepository {
+ fun saveNewMetric(metric: BuildMetric): Long
+ fun saveTemporaryMetric(metric: BuildMetric): Long
+
+ fun isDayMetricExists(): Boolean
+
+ fun getDayMetric(): Pair
+ fun getMetrics(period: Pair): List
+ fun getTemporaryMetrics(): List
+
+ fun updateDayMetric(number: Long, metric: BuildMetric): Boolean
+
+ fun dropOutdatedTemporaryMetrics(): Boolean
+ fun dropMetrics(): Boolean
+ fun dropOutdatedMetrics()
+
+ fun getSingleMetric(key: String, branch: String): String?
+ fun updateSingleMetric(key: String, branch: String, value: String): Boolean
+ fun saveSingleMetric(key: String, branch: String, value: String): Boolean
+ fun dropSingleMetric(key: String, branch: String): Boolean
+ fun dropSingleMetrics(): Boolean
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/GetMetricsUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/GetMetricsUseCase.kt
new file mode 100644
index 00000000..bb0692b2
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/GetMetricsUseCase.kt
@@ -0,0 +1,43 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.usecase
+
+import io.github.janbarari.gradle.core.UseCase
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+
+/**
+ * Gets the saved metrics from the database.
+ */
+class GetMetricsUseCase(
+ private val repo: DatabaseRepository
+): UseCase, List>() {
+
+ /**
+ * Get list of metrics from database by giving the start & end timestamp.
+ */
+ override suspend fun execute(input: Pair): List {
+ return repo.getMetrics(input)
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/GetModulesTimelineUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/GetModulesTimelineUseCase.kt
new file mode 100644
index 00000000..25ef2e7c
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/GetModulesTimelineUseCase.kt
@@ -0,0 +1,47 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.usecase
+
+import com.squareup.moshi.Moshi
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesTimelineMetric
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesTimelineMetricJsonAdapter
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCase
+import io.github.janbarari.gradle.extension.isNotNull
+
+class GetModulesTimelineUseCase(
+ val moshi: Moshi,
+ val repo: DatabaseRepository
+): UseCase() {
+
+ override suspend fun execute(branch: String): ModulesTimelineMetric? {
+ val result = repo.getSingleMetric(
+ key = "modulesExecTimeline",
+ branch = branch
+ )
+ if (result.isNotNull())
+ return ModulesTimelineMetricJsonAdapter(moshi).fromJson(result!!)
+ return null
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/SaveMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/SaveMetricUseCase.kt
new file mode 100644
index 00000000..a3975253
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/SaveMetricUseCase.kt
@@ -0,0 +1,126 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.usecase
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.analytics.metric.cachehit.update.UpdateCacheHitMetricStage
+import io.github.janbarari.gradle.analytics.metric.cachehit.update.UpdateCacheHitMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.configurationprocess.update.UpdateConfigurationProcessMetricStage
+import io.github.janbarari.gradle.analytics.metric.configurationprocess.update.UpdateConfigurationProcessMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.dependencydetails.update.UpdateDependencyDetailsMetricStage
+import io.github.janbarari.gradle.analytics.metric.dependencydetails.update.UpdateDependencyDetailsMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.dependencyresolveprocess.update.UpdateDependencyResolveProcessMetricStage
+import io.github.janbarari.gradle.analytics.metric.dependencyresolveprocess.update.UpdateDependencyResolveProcessMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.executionprocess.update.UpdateExecutionProcessMetricStage
+import io.github.janbarari.gradle.analytics.metric.executionprocess.update.UpdateExecutionProcessMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.initializationprocess.update.UpdateInitializationProcessMetricStage
+import io.github.janbarari.gradle.analytics.metric.initializationprocess.update.UpdateInitializationProcessMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.modulesbuildheatmap.update.UpdateModulesBuildHeatmapMetricStage
+import io.github.janbarari.gradle.analytics.metric.modulesbuildheatmap.update.UpdateModulesBuildHeatmapMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.modulescrashcount.update.UpdateModulesCrashCountMetricStage
+import io.github.janbarari.gradle.analytics.metric.modulescrashcount.update.UpdateModulesCrashCountMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.modulesdependencygraph.update.UpdateModulesDependencyGraphMetricStage
+import io.github.janbarari.gradle.analytics.metric.modulesdependencygraph.update.UpdateModulesDependencyGraphMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.modulesexecutionprocess.update.UpdateModulesExecutionProcessMetricStage
+import io.github.janbarari.gradle.analytics.metric.modulesexecutionprocess.update.UpdateModulesExecutionProcessMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.modulesmethodcount.update.UpdateModulesMethodCountMetricStage
+import io.github.janbarari.gradle.analytics.metric.modulesmethodcount.update.UpdateModulesMethodCountMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.modulesourcecount.update.UpdateModulesSourceCountMetricStage
+import io.github.janbarari.gradle.analytics.metric.modulesourcecount.update.UpdateModulesSourceCountMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.modulessourcesize.update.UpdateModulesSourceSizeMetricStage
+import io.github.janbarari.gradle.analytics.metric.modulessourcesize.update.UpdateModulesSourceSizeMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.noncacheabletasks.update.UpdateNonCacheableTasksMetricStage
+import io.github.janbarari.gradle.analytics.metric.noncacheabletasks.update.UpdateNonCacheableTasksMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.overallbuildprocess.update.UpdateOverallBuildProcessMetricStage
+import io.github.janbarari.gradle.analytics.metric.overallbuildprocess.update.UpdateOverallBuildProcessMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.paralleexecutionrate.update.UpdateParallelExecutionRateMetricStage
+import io.github.janbarari.gradle.analytics.metric.paralleexecutionrate.update.UpdateParallelExecutionRateMetricUseCase
+import io.github.janbarari.gradle.analytics.metric.successbuildrate.update.UpdateSuccessBuildRateMetricStage
+import io.github.janbarari.gradle.analytics.metric.successbuildrate.update.UpdateSuccessBuildRateMetricUseCase
+import io.github.janbarari.gradle.core.UseCase
+
+/**
+ * Saves daily build metrics.
+ */
+class SaveMetricUseCase(
+ private val repo: DatabaseRepository,
+ private val updateInitializationProcessMetricUseCase: UpdateInitializationProcessMetricUseCase,
+ private val updateConfigurationProcessMetricUseCase: UpdateConfigurationProcessMetricUseCase,
+ private val updateExecutionProcessMetricUseCase: UpdateExecutionProcessMetricUseCase,
+ private val updateOverallBuildProcessMetricUseCase: UpdateOverallBuildProcessMetricUseCase,
+ private val updateModulesSourceCountMetricUseCase: UpdateModulesSourceCountMetricUseCase,
+ private val updateModulesMethodCountMetricUseCase: UpdateModulesMethodCountMetricUseCase,
+ private val updateCacheHitMetricUseCase: UpdateCacheHitMetricUseCase,
+ private val updateSuccessBuildRateMetricUseCase: UpdateSuccessBuildRateMetricUseCase,
+ private val updateDependencyResolveProcessMetricUseCase: UpdateDependencyResolveProcessMetricUseCase,
+ private val updateParallelExecutionRateMetricUseCase: UpdateParallelExecutionRateMetricUseCase,
+ private val updateModulesExecutionProcessMetricUseCase: UpdateModulesExecutionProcessMetricUseCase,
+ private val updateModulesDependencyGraphMetricUseCase: UpdateModulesDependencyGraphMetricUseCase,
+ private val updateModulesBuildHeatmapMetricUseCase: UpdateModulesBuildHeatmapMetricUseCase,
+ private val updateDependencyDetailsMetricUseCase: UpdateDependencyDetailsMetricUseCase,
+ private val updateNonCacheableTasksMetricUseCase: UpdateNonCacheableTasksMetricUseCase,
+ private val updateModulesSourceSizeMetricUseCase: UpdateModulesSourceSizeMetricUseCase,
+ private val updateModulesCrashCountMetricUseCase: UpdateModulesCrashCountMetricUseCase,
+) : UseCase() {
+
+ /**
+ * Upsert the daily metric in the database.
+ *
+ * @param input BuildMetric of the build.
+ */
+ override suspend fun execute(input: BuildMetric): Long {
+ if (!repo.isDayMetricExists()) return repo.saveNewMetric(input)
+
+ val pipeline = UpdateMetricPipeline(UpdateInitializationProcessMetricStage(updateInitializationProcessMetricUseCase))
+ .addStage(UpdateConfigurationProcessMetricStage(updateConfigurationProcessMetricUseCase))
+ .addStage(UpdateExecutionProcessMetricStage(updateExecutionProcessMetricUseCase))
+ .addStage(UpdateOverallBuildProcessMetricStage(updateOverallBuildProcessMetricUseCase))
+ .addStage(UpdateModulesSourceCountMetricStage(updateModulesSourceCountMetricUseCase))
+ .addStage(UpdateModulesMethodCountMetricStage(updateModulesMethodCountMetricUseCase))
+ .addStage(UpdateCacheHitMetricStage(updateCacheHitMetricUseCase))
+ .addStage(UpdateSuccessBuildRateMetricStage(updateSuccessBuildRateMetricUseCase))
+ .addStage(UpdateDependencyResolveProcessMetricStage(updateDependencyResolveProcessMetricUseCase))
+ .addStage(UpdateParallelExecutionRateMetricStage(updateParallelExecutionRateMetricUseCase))
+ .addStage(UpdateModulesExecutionProcessMetricStage(updateModulesExecutionProcessMetricUseCase))
+ .addStage(UpdateModulesDependencyGraphMetricStage(updateModulesDependencyGraphMetricUseCase))
+ .addStage(UpdateModulesBuildHeatmapMetricStage(updateModulesBuildHeatmapMetricUseCase))
+ .addStage(UpdateDependencyDetailsMetricStage(updateDependencyDetailsMetricUseCase))
+ .addStage(UpdateNonCacheableTasksMetricStage(updateNonCacheableTasksMetricUseCase))
+ .addStage(UpdateModulesSourceSizeMetricStage(updateModulesSourceSizeMetricUseCase))
+ .addStage(UpdateModulesCrashCountMetricStage(updateModulesCrashCountMetricUseCase))
+ .execute(
+ BuildMetric(
+ branch = input.branch,
+ requestedTasks = input.requestedTasks,
+ createdAt = input.createdAt,
+ gitHeadCommitHash = input.gitHeadCommitHash
+ )
+ )
+
+ val dayMetricNumber = repo.getDayMetric().second
+ repo.updateDayMetric(dayMetricNumber, pipeline)
+ return dayMetricNumber
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/SaveTemporaryMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/SaveTemporaryMetricUseCase.kt
new file mode 100644
index 00000000..57ec6cb7
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/SaveTemporaryMetricUseCase.kt
@@ -0,0 +1,40 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.usecase
+
+import io.github.janbarari.gradle.core.UseCase
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+
+/**
+ * Saves day build metrics.
+ * It's temporary and only valid for a day. to measure a valid result from all
+ * build metrics of the day.
+ */
+class SaveTemporaryMetricUseCase(private val repo: DatabaseRepository): UseCase() {
+
+ override suspend fun execute(input: BuildMetric): Long {
+ return repo.saveTemporaryMetric(input)
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/UpdateMetricPipeline.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/UpdateMetricPipeline.kt
new file mode 100644
index 00000000..9ec01c5f
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/UpdateMetricPipeline.kt
@@ -0,0 +1,29 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.usecase
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Pipeline
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateMetricPipeline(firstStage: Stage): Pipeline(firstStage)
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/UpsertModulesTimelineUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/UpsertModulesTimelineUseCase.kt
new file mode 100644
index 00000000..62937839
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/domain/usecase/UpsertModulesTimelineUseCase.kt
@@ -0,0 +1,57 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.domain.usecase
+
+import com.squareup.moshi.Moshi
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesTimelineMetric
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesTimelineMetricJsonAdapter
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCase
+import io.github.janbarari.gradle.extension.isNotNull
+
+class UpsertModulesTimelineUseCase(
+ private val moshi: Moshi,
+ private val repo: DatabaseRepository
+): UseCase, Boolean>() {
+
+ override suspend fun execute(input: Pair): Boolean {
+ val branch = input.first
+ val model = input.second
+
+ if (repo.getSingleMetric(key = "modulesExecTimeline", branch = branch).isNotNull()) {
+ return repo.updateSingleMetric(
+ key = "modulesExecTimeline",
+ branch = branch,
+ value = ModulesTimelineMetricJsonAdapter(moshi).toJson(model)
+ )
+ }
+
+ return repo.saveSingleMetric(
+ key = "modulesExecTimeline",
+ branch = branch,
+ value = ModulesTimelineMetricJsonAdapter(moshi).toJson(model)
+ )
+
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/buildstatus/render/CreateBuildStatusReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/buildstatus/render/CreateBuildStatusReportStage.kt
new file mode 100644
index 00000000..7e90ac14
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/buildstatus/render/CreateBuildStatusReportStage.kt
@@ -0,0 +1,151 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.buildstatus.render
+
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.BuildStatusReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.millisToSeconds
+import io.github.janbarari.gradle.utils.MathUtils
+
+class CreateBuildStatusReportStage(
+ private val modules: List,
+ private val metrics: List
+) : Stage {
+
+ override suspend fun process(input: Report): Report {
+ return input.apply {
+ buildStatusReport = BuildStatusReport(
+ cumulativeOverallBuildProcessBySeconds = getCumulativeOverallBuildProcessInSeconds(),
+ avgOverallBuildProcessBySeconds = getAvgOverallBuildProcessInSeconds(),
+ totalBuildProcessCount = metrics.size,
+ totalProjectModulesCount = modules.size,
+ cumulativeDependencyResolveBySeconds = getCumulativeDependencyResolveInSeconds(),
+ cumulativeParallelExecutionBySeconds = getCumulativeParallelExecutionInSeconds(),
+ avgParallelExecutionRate = getAvgParallelExecutionRate(),
+ totalFailedBuildCount = getTotalFailedBuildCount(),
+ totalSucceedBuildCount = getTotalSuccessBuildCount(),
+ avgCacheHitRate = getAvgCacheHitRate(),
+ avgInitializationProcessByMillis = getAvgInitializationProcessInMillis(),
+ avgConfigurationProcessByMillis = getAvgConfigurationProcessInMillis(),
+ avgExecutionProcessBySeconds = getAvgExecutionProcessInSeconds()
+ )
+ }
+ }
+
+ fun getCumulativeOverallBuildProcessInSeconds(): Long {
+ return metrics
+ .filter { it.overallBuildProcessMetric.isNotNull() }
+ .sumOf { metric ->
+ metric.overallBuildProcessMetric!!.median.millisToSeconds()
+ }
+ }
+
+ fun getAvgOverallBuildProcessInSeconds(): Long {
+ return MathUtils.longMedian(
+ metrics.filter { it.overallBuildProcessMetric.isNotNull() }
+ .map { metric ->
+ metric.overallBuildProcessMetric!!.median.millisToSeconds()
+ }
+ )
+ }
+
+ fun getCumulativeDependencyResolveInSeconds(): Long {
+ return metrics
+ .filter { it.dependencyResolveProcessMetric.isNotNull() }
+ .sumOf { metric ->
+ metric.dependencyResolveProcessMetric!!.median.millisToSeconds()
+ }
+ }
+
+ fun getCumulativeParallelExecutionInSeconds(): Long {
+ return metrics
+ .filter { it.executionProcessMetric.isNotNull() && it.parallelExecutionRateMetric.isNotNull() }
+ .sumOf { metric ->
+ MathUtils.sumWithPercentage(
+ metric.executionProcessMetric!!.median.millisToSeconds(),
+ metric.parallelExecutionRateMetric!!.medianRate.toInt()
+ )
+ }
+ }
+
+ fun getAvgParallelExecutionRate(): Float {
+ return MathUtils.floatMedian(
+ metrics.filter { it.parallelExecutionRateMetric.isNotNull() }
+ .map { metric ->
+ metric.parallelExecutionRateMetric!!.medianRate.toFloat()
+ }
+ )
+ }
+
+ fun getTotalFailedBuildCount(): Int {
+ return metrics
+ .filter { it.successBuildRateMetric.isNotNull() }
+ .sumOf { it.successBuildRateMetric!!.fails }
+ }
+
+ fun getTotalSuccessBuildCount(): Int {
+ return metrics
+ .filter { it.successBuildRateMetric.isNotNull() }
+ .sumOf { it.successBuildRateMetric!!.successes }
+ }
+
+ fun getAvgCacheHitRate(): Float {
+ return MathUtils.floatMedian(
+ metrics
+ .filter { it.cacheHitMetric.isNotNull() }
+ .map { it.cacheHitMetric!!.rate.toFloat() }
+ )
+ }
+
+ fun getAvgInitializationProcessInMillis(): Long {
+ return MathUtils.longMedian(
+ metrics.filter { it.initializationProcessMetric.isNotNull() }
+ .map { metric ->
+ metric.initializationProcessMetric!!.median
+ }
+ )
+ }
+
+ fun getAvgConfigurationProcessInMillis(): Long {
+ return MathUtils.longMedian(
+ metrics.filter { it.configurationProcessMetric.isNotNull() }
+ .map { metric ->
+ metric.configurationProcessMetric!!.median
+ }
+ )
+ }
+
+ fun getAvgExecutionProcessInSeconds(): Long {
+ return MathUtils.longMedian(
+ metrics.filter { it.executionProcessMetric.isNotNull() }
+ .map { metric ->
+ metric.executionProcessMetric!!.median.millisToSeconds()
+ }
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/buildstatus/render/RenderBuildStatusReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/buildstatus/render/RenderBuildStatusReportStage.kt
new file mode 100644
index 00000000..39ffdeae
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/buildstatus/render/RenderBuildStatusReportStage.kt
@@ -0,0 +1,84 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.buildstatus.render
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.round
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.DateTimeUtils
+import io.github.janbarari.gradle.utils.HtmlUtils
+
+class RenderBuildStatusReportStage(
+ private val report: Report
+): Stage {
+
+ companion object {
+ private const val BUILD_STATUS_METRIC_TEMPLATE_ID = "%build-status-metric%"
+ private const val BUILD_STATUS_METRIC_TEMPLATE_FILENAME = "build-status-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.buildStatusReport.isNull())
+ return input.replace(BUILD_STATUS_METRIC_TEMPLATE_ID, getEmptyRender())
+
+ return input.replace(BUILD_STATUS_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Build Status is not available!")
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(BUILD_STATUS_METRIC_TEMPLATE_FILENAME)
+ report.buildStatusReport.whenNotNull {
+ renderedTemplate = renderedTemplate
+ .replace("%cumulative-build-process-duration%",
+ DateTimeUtils.convertSecondsToHumanReadableTime(cumulativeOverallBuildProcessBySeconds)
+ )
+ .replace("%avg-build-process-duration%",
+ DateTimeUtils.convertSecondsToHumanReadableTime(avgOverallBuildProcessBySeconds)
+ )
+ .replace("%total-build-process-count%", totalBuildProcessCount.toString())
+ .replace("%total-modules-count%", totalProjectModulesCount.toString())
+ .replace("%cumulative-parallel-exec-duration%",
+ DateTimeUtils.convertSecondsToHumanReadableTime(cumulativeParallelExecutionBySeconds)
+ )
+ .replace("%avg-parallel-exec-rate%", "${avgParallelExecutionRate.round()}%")
+ .replace("%total-succeed-build-count%", "$totalSucceedBuildCount")
+ .replace("%total-failed-build-count%", "$totalFailedBuildCount")
+ .replace("%avg-cache-hit-rate%", "${avgCacheHitRate.round()}%")
+ .replace("%cumulative-dependency-resolve-duration%",
+ DateTimeUtils.convertSecondsToHumanReadableTime(cumulativeDependencyResolveBySeconds)
+ )
+ .replace("%avg-initialization-process-duration%", "${avgInitializationProcessByMillis}ms")
+ .replace("%avg-configuration-process-duration%", "${avgConfigurationProcessByMillis}ms")
+ .replace("%avg-execution-process-duration%", "${avgExecutionProcessBySeconds}s")
+ }
+ return renderedTemplate
+ }
+
+
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/create/CreateCacheHitMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/create/CreateCacheHitMetricStage.kt
new file mode 100644
index 00000000..578054fd
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/create/CreateCacheHitMetricStage.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.cachehit.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateCacheHitMetricStage(
+ private val buildInfo: BuildInfo,
+ private val createCacheHitMetricUseCase: CreateCacheHitMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ if (buildInfo.isSuccessful) {
+ cacheHitMetric = createCacheHitMetricUseCase.execute(buildInfo)
+ }
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/create/CreateCacheHitMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/create/CreateCacheHitMetricUseCase.kt
new file mode 100644
index 00000000..2a42c91c
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/create/CreateCacheHitMetricUseCase.kt
@@ -0,0 +1,72 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.cachehit.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.CacheHitMetric
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModuleCacheHit
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.core.UseCase
+import io.github.janbarari.gradle.extension.toPercentageOf
+import io.github.janbarari.gradle.extension.whenEach
+
+class CreateCacheHitMetricUseCase(
+ private val modules: List
+): UseCase() {
+
+ override suspend fun execute(input: BuildInfo): CacheHitMetric {
+ var cachedTasksCount = 0
+ input.executedTasks.whenEach {
+ if (!isSkipped) {
+ if (isUpToDate || isFromCache) {
+ cachedTasksCount++
+ }
+ }
+ }
+ val overallCacheHitRate = cachedTasksCount.toPercentageOf(input.executedTasks.filter { it.isSkipped.not() }.size)
+
+ val modulesCacheHit = mutableListOf()
+ modules.whenEach {
+ var moduleCachedTasksCount = 0
+ var moduleTasksCount = 0
+ input.executedTasks.filter { it.path.startsWith(path) }
+ .whenEach {
+ moduleTasksCount++
+ if (!isSkipped) {
+ if (isUpToDate || isFromCache) {
+ moduleCachedTasksCount++
+ }
+ }
+ }
+ val moduleCacheHitRate = moduleCachedTasksCount.toPercentageOf(moduleTasksCount)
+ modulesCacheHit.add(
+ ModuleCacheHit(
+ path = path,
+ rate = moduleCacheHitRate.toLong()
+ )
+ )
+ }
+ return CacheHitMetric(overallCacheHitRate.toLong(), modulesCacheHit)
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/report/CreateCacheHitReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/report/CreateCacheHitReportStage.kt
new file mode 100644
index 00000000..0d8c921a
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/report/CreateCacheHitReportStage.kt
@@ -0,0 +1,162 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.cachehit.report
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.CacheHitReport
+import io.github.janbarari.gradle.analytics.domain.model.report.ModuleCacheHit
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.diffPercentageOf
+import io.github.janbarari.gradle.extension.hasMultipleItems
+import io.github.janbarari.gradle.extension.hasSingleItem
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.minimize
+import io.github.janbarari.gradle.extension.whenEach
+
+class CreateCacheHitReportStage(
+ private val metrics: List
+) : Stage {
+
+ override suspend fun process(input: Report): Report {
+ val metrics = metrics.filter {
+ it.cacheHitMetric.isNotNull()
+ }
+
+ if (metrics.hasSingleItem()) {
+ return input.apply {
+ cacheHitReport = generateSingleItemReport(metrics.single())
+ }
+ }
+
+ if (metrics.hasMultipleItems()) {
+ return input.apply {
+ cacheHitReport = generateMultipleItemsReport(metrics)
+ }
+ }
+
+ return input
+ }
+
+ private fun generateSingleItemReport(metric: BuildMetric): CacheHitReport {
+ val modules = mutableListOf()
+ val overallHit = metric.cacheHitMetric!!.rate
+
+ val overallHitTimespanChartPoint = TimespanPoint(
+ value = overallHit,
+ from = metric.createdAt
+ )
+
+ val overallValues = listOf(
+ overallHitTimespanChartPoint
+ )
+
+ metric.cacheHitMetric!!.modules.whenEach {
+ val values = mutableListOf(
+ TimespanPoint(
+ value = rate, from = metric.createdAt
+ )
+ )
+ modules.add(
+ ModuleCacheHit(
+ path = path,
+ rate = rate,
+ diffRate = null,
+ meanValues = values
+ )
+ )
+ }
+
+ return CacheHitReport(
+ modules = modules.sortedByDescending { it.rate },
+ overallRate = overallHit,
+ overallDiffRate = null,
+ overallMeanValues = overallValues
+ )
+ }
+
+ private fun generateMultipleItemsReport(metrics: List): CacheHitReport {
+ val firstCacheHitRatio = metrics.first().cacheHitMetric!!.rate
+ val lastCacheHitRatio = metrics.last().cacheHitMetric!!.rate
+
+ val overallDiffRatio = firstCacheHitRatio.diffPercentageOf(lastCacheHitRatio)
+
+ val overallHit = metrics.last().cacheHitMetric!!.rate
+
+ val overallValuesTimestampChartPoints = mutableListOf()
+ metrics.whenEach {
+ overallValuesTimestampChartPoints.add(
+ TimespanPoint(
+ value = cacheHitMetric!!.rate, from = createdAt
+ )
+ )
+ }
+ val overallMeanValues = overallValuesTimestampChartPoints.minimize(12)
+
+ val modules = mutableListOf()
+ metrics.last().cacheHitMetric!!.modules.whenEach {
+ modules.add(
+ ModuleCacheHit(
+ path = path,
+ rate = rate,
+ diffRate = calculateModuleCacheHitDiffRatio(metrics, path, rate),
+ meanValues = getModuleChartPoints(path)
+ )
+ )
+ }
+
+ return CacheHitReport(
+ modules = modules,
+ overallMeanValues = overallMeanValues,
+ overallRate = overallHit,
+ overallDiffRate = overallDiffRatio
+ )
+ }
+
+ private fun calculateModuleCacheHitDiffRatio(metrics: List, path: String, value: Long): Float? {
+ return metrics.first().cacheHitMetric!!
+ .modules.find { it.path == path }?.rate?.diffPercentageOf(value)
+ }
+
+ private fun getModuleChartPoints(path: String): List {
+ val timestampChartPoints = mutableListOf()
+ metrics
+ .filter {
+ it.cacheHitMetric.isNotNull()
+ }.whenEach {
+ cacheHitMetric!!.modules
+ .filter { it.path == path }
+ .whenEach {
+ timestampChartPoints.add(
+ TimespanPoint(
+ value = rate,
+ from = createdAt
+ )
+ )
+ }
+ }
+
+ return timestampChartPoints.minimize(12)
+ }
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/report/RenderCacheHitReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/report/RenderCacheHitReportStage.kt
new file mode 100644
index 00000000..ae847748
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/report/RenderCacheHitReportStage.kt
@@ -0,0 +1,160 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.cachehit.report
+
+import io.github.janbarari.gradle.analytics.domain.model.report.ModuleCacheHit
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.mapToChartPoints
+import io.github.janbarari.gradle.extension.toArrayString
+import io.github.janbarari.gradle.extension.toIntList
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+
+class RenderCacheHitReportStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val CACHE_HIT_METRIC_TEMPLATE_ID = "%cache-hit-metric%"
+ private const val CACHE_HIT_METRIC_TEMPLATE_FILE_NAME = "cache-hit-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.cacheHitReport.isNull())
+ return input.replace(CACHE_HIT_METRIC_TEMPLATE_ID, getEmptyRender())
+
+ return input.replace(CACHE_HIT_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Cache Hit is not available!")
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(CACHE_HIT_METRIC_TEMPLATE_FILE_NAME)
+ report.cacheHitReport.whenNotNull {
+ val tableData = buildString {
+ modules.forEachIndexed { index, it ->
+ var diffRatioRender = "- | "
+ it.diffRate.whenNotNull {
+ diffRatioRender = if (this > 0)
+ "+${this}% | "
+ else if (this < 0)
+ "-${this}% | "
+ else
+ "Equals | "
+ }
+ append("""
+
+ ${index + 1} |
+ ${it.path} |
+ ${it.rate}% |
+ $diffRatioRender
+
+ """.trimIndent())
+ }
+ }
+
+ val overallCacheHit = "$overallRate%"
+ var overallDiffRatioRender = "- | "
+ overallDiffRate.whenNotNull {
+ overallDiffRatioRender = if (this > 0)
+ "+${this}% | "
+ else if (this < 0)
+ "-${this}% | "
+ else
+ "Equals | "
+ }
+
+ var bestChartValues = "[]"
+ var worstChartValues = "[]"
+ var bwLabels = "[]"
+ if (modules.isNotEmpty()) {
+ bestChartValues = modules
+ .first { it.path == getBestModulePath(modules) }
+ .meanValues
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ worstChartValues = modules
+ .first { it.path == getWorstModulePath(modules) }
+ .meanValues
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ bwLabels = modules
+ .first { it.path == getWorstModulePath(modules) }
+ .meanValues
+ .mapToChartPoints()
+ .map { it.description }
+ .toArrayString()
+ }
+
+ renderedTemplate = renderedTemplate
+ .replace("%chart-values%", getOverallChartValues().toString())
+ .replace("%chart-labels%", getOverallChartLabels().toArrayString())
+ .replace("%table-data%", tableData)
+ .replace("%overall-cache-hit%", overallCacheHit)
+ .replace("%overall-diff-rate%", overallDiffRatioRender)
+ .replace("%best-values%", bestChartValues)
+ .replace("%worst-values%", worstChartValues)
+ .replace("%bw-labels%", bwLabels)
+ .replace("%worst-module-name%", "\"${getWorstModulePath(modules)}\"")
+ .replace("%best-module-name%", "\"${getBestModulePath(modules)}\"")
+ }
+ return renderedTemplate
+ }
+
+ fun getBestModulePath(modules: List): String? {
+ if (modules.isEmpty()) return null
+ return modules.sortedByDescending { module ->
+ module.meanValues.sumOf { it.value }
+ }.first().path
+ }
+
+ fun getWorstModulePath(modules: List): String? {
+ if (modules.isEmpty()) return null
+ return modules.sortedByDescending { module ->
+ module.meanValues.sumOf { it.value }
+ }.last().path
+ }
+
+ fun getOverallChartValues(): List {
+ return report.cacheHitReport!!
+ .overallMeanValues
+ .map { it.value }
+ .toIntList()
+ }
+
+ fun getOverallChartLabels(): List {
+ return report.cacheHitReport!!
+ .overallMeanValues
+ .mapToChartPoints()
+ .map { it.description }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/update/UpdateCacheHitMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/update/UpdateCacheHitMetricStage.kt
new file mode 100644
index 00000000..5e942e61
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/update/UpdateCacheHitMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.cachehit.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateCacheHitMetricStage(
+ private val updateCacheHitMetricUseCase: UpdateCacheHitMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ cacheHitMetric = updateCacheHitMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/update/UpdateCacheHitMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/update/UpdateCacheHitMetricUseCase.kt
new file mode 100644
index 00000000..d69d90c8
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/cachehit/update/UpdateCacheHitMetricUseCase.kt
@@ -0,0 +1,66 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.cachehit.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.metric.CacheHitMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.modify
+import io.github.janbarari.gradle.utils.MathUtils
+
+class UpdateCacheHitMetricUseCase(
+ private val repo: DatabaseRepository
+) : UseCaseNoInput() {
+
+ override suspend fun execute(): CacheHitMetric? {
+ val temporaryMetrics = repo.getTemporaryMetrics()
+
+ val hitRates = temporaryMetrics.filter { it.cacheHitMetric.isNotNull() }
+ .map { it.cacheHitMetric!!.rate }
+
+ val modules = temporaryMetrics.last().cacheHitMetric?.modules?.modify {
+ rate = getModuleMeanCacheHit(path, temporaryMetrics)
+ } ?: return null
+
+ return CacheHitMetric(
+ rate = MathUtils.longMean(hitRates),
+ modules = modules
+ )
+ }
+
+ private fun getModuleMeanCacheHit(path: String, metrics: List): Long {
+ val hitRates = metrics
+ .filter {
+ it.cacheHitMetric.isNotNull()
+ && it.cacheHitMetric!!.modules.find { module -> module.path == path }.isNotNull()
+ }
+ .map {
+ it.cacheHitMetric!!.modules.find { module -> module.path == path }!!.rate
+ }
+
+ return MathUtils.longMean(hitRates)
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/create/CreateConfigurationProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/create/CreateConfigurationProcessMetricStage.kt
new file mode 100644
index 00000000..ff665ac2
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/create/CreateConfigurationProcessMetricStage.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.configurationprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateConfigurationProcessMetricStage(
+ private val buildInfo: BuildInfo,
+ private val createConfigurationProcessMetricUseCase: CreateConfigurationProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ if (buildInfo.isSuccessful) {
+ configurationProcessMetric = createConfigurationProcessMetricUseCase.execute(buildInfo)
+ }
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/create/CreateConfigurationProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/create/CreateConfigurationProcessMetricUseCase.kt
new file mode 100644
index 00000000..e4e0968b
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/create/CreateConfigurationProcessMetricUseCase.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.configurationprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.ConfigurationProcessMetric
+import io.github.janbarari.gradle.core.UseCase
+
+class CreateConfigurationProcessMetricUseCase: UseCase() {
+
+ override suspend fun execute(input: BuildInfo): ConfigurationProcessMetric {
+ return ConfigurationProcessMetric(
+ median = input.getConfigurationDuration().toMillis(),
+ mean = input.getConfigurationDuration().toMillis()
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/report/CreateConfigurationProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/report/CreateConfigurationProcessReportStage.kt
new file mode 100644
index 00000000..62f59a00
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/report/CreateConfigurationProcessReportStage.kt
@@ -0,0 +1,68 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.configurationprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ConfigurationProcessReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isBiggerEquals
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.mapToConfigurationMeanTimespanChartPoints
+import io.github.janbarari.gradle.extension.mapToConfigurationMedianTimespanChartPoints
+import io.github.janbarari.gradle.extension.whenEmpty
+
+class CreateConfigurationProcessReportStage(
+ private val metrics: List
+) : Stage {
+
+ companion object {
+ private const val SKIP_THRESHOLD_IN_MS = 50L
+ }
+
+ override suspend fun process(input: Report): Report {
+ val medianChartPoints = metrics.filter { metric ->
+ metric.configurationProcessMetric.isNotNull() &&
+ metric.configurationProcessMetric?.median?.isBiggerEquals(SKIP_THRESHOLD_IN_MS) ?: false
+ }.mapToConfigurationMedianTimespanChartPoints()
+ .whenEmpty {
+ return input
+ }
+
+ val meanChartPoints = metrics.filter { metric ->
+ metric.configurationProcessMetric.isNotNull() &&
+ metric.configurationProcessMetric?.mean?.isBiggerEquals(SKIP_THRESHOLD_IN_MS) ?: false
+ }.mapToConfigurationMeanTimespanChartPoints()
+ .whenEmpty {
+ return input
+ }
+
+ return input.apply {
+ configurationProcessReport = ConfigurationProcessReport(
+ medianValues = medianChartPoints,
+ meanValues = meanChartPoints,
+ )
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/report/RenderConfigurationProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/report/RenderConfigurationProcessReportStage.kt
new file mode 100644
index 00000000..1818c251
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/report/RenderConfigurationProcessReportStage.kt
@@ -0,0 +1,102 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.configurationprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.mapToChartPoints
+import io.github.janbarari.gradle.extension.maxValue
+import io.github.janbarari.gradle.extension.minValue
+import io.github.janbarari.gradle.extension.minimize
+import io.github.janbarari.gradle.extension.toArrayString
+import io.github.janbarari.gradle.extension.toIntList
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+import io.github.janbarari.gradle.utils.MathUtils
+
+/**
+ * Generates html result for [io.github.janbarari.gradle.analytics.domain.model.report.ConfigurationProcessReport].
+ */
+class RenderConfigurationProcessReportStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val CHART_MAX_COLUMNS = 12
+ private const val CHART_SUGGESTED_MIN_MAX_PERCENTAGE = 30
+ private const val CONFIGURATION_METRIC_TEMPLATE_ID = "%configuration-process-metric%"
+ private const val CONFIGURATION_METRIC_TEMPLATE_FILE_NAME = "configuration-process-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.configurationProcessReport.isNull()) {
+ return input.replace(CONFIGURATION_METRIC_TEMPLATE_ID, getEmptyRender())
+ }
+
+ return input.replace(CONFIGURATION_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(CONFIGURATION_METRIC_TEMPLATE_FILE_NAME)
+ report.configurationProcessReport.whenNotNull {
+ val medianChartValues = medianValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ val meanChartValues = meanValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ val chartLabels = medianValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.description }
+ .toArrayString()
+
+ val maximumValue = Math.max(medianValues.maxValue(), meanValues.maxValue())
+ val minimumValue = Math.min(medianValues.minValue(), meanValues.minValue())
+ val chartSuggestedMaxValue = MathUtils.sumWithPercentage(maximumValue, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+ val chartSuggestedMinValue = MathUtils.deductWithPercentage(minimumValue, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+
+ renderedTemplate = renderedTemplate
+ .replace("%suggested-max-value%", chartSuggestedMaxValue.toString())
+ .replace("%suggested-min-value%", chartSuggestedMinValue.toString())
+ .replace("%chart-median-values%", medianChartValues)
+ .replace("%chart-mean-values%", meanChartValues)
+ .replace("%chart-labels%", chartLabels)
+ }
+ return renderedTemplate
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Configuration Process is not available!")
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/update/UpdateConfigurationProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/update/UpdateConfigurationProcessMetricStage.kt
new file mode 100644
index 00000000..834ec99f
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/update/UpdateConfigurationProcessMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.configurationprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateConfigurationProcessMetricStage(
+ private val updateConfigurationProcessMetricUseCase: UpdateConfigurationProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ configurationProcessMetric = updateConfigurationProcessMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/update/UpdateConfigurationProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/update/UpdateConfigurationProcessMetricUseCase.kt
new file mode 100644
index 00000000..6bb6257b
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/configurationprocess/update/UpdateConfigurationProcessMetricUseCase.kt
@@ -0,0 +1,66 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.configurationprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.ConfigurationProcessMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.isBiggerEquals
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.extension.whenTrue
+import io.github.janbarari.gradle.utils.MathUtils
+
+/**
+ * Generates a new metric with Median mathematics based on temporary metrics.
+ */
+class UpdateConfigurationProcessMetricUseCase(
+ private val repo: DatabaseRepository
+) : UseCaseNoInput() {
+
+ companion object {
+ private const val SKIP_THRESHOLD_IN_MS = 50L
+ }
+
+ override suspend fun execute(): ConfigurationProcessMetric {
+ val medianValues = mutableListOf()
+ val meanValues = mutableListOf()
+ repo.getTemporaryMetrics().whenEach {
+ configurationProcessMetric.whenNotNull {
+ // In order to have accurate metric, don't add metric value in Median dataset if it's under 50 milliseconds.
+ median.isBiggerEquals(SKIP_THRESHOLD_IN_MS).whenTrue {
+ medianValues.add(median)
+ }
+ mean.isBiggerEquals(SKIP_THRESHOLD_IN_MS).whenTrue {
+ meanValues.add(mean)
+ }
+ }
+ }
+
+ return ConfigurationProcessMetric(
+ median = MathUtils.longMedian(medianValues),
+ mean = MathUtils.longMean(meanValues)
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/create/CreateDependencyDetailsMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/create/CreateDependencyDetailsMetricStage.kt
new file mode 100644
index 00000000..10c131f3
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/create/CreateDependencyDetailsMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencydetails.create
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateDependencyDetailsMetricStage(
+ private val createDependencyDetailsMetricUseCase: CreateDependencyDetailsMetricUseCase
+) : Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ dependencyDetailsMetric = createDependencyDetailsMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/create/CreateDependencyDetailsMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/create/CreateDependencyDetailsMetricUseCase.kt
new file mode 100644
index 00000000..da65467d
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/create/CreateDependencyDetailsMetricUseCase.kt
@@ -0,0 +1,39 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencydetails.create
+
+import io.github.janbarari.gradle.analytics.domain.model.Dependency
+import io.github.janbarari.gradle.analytics.domain.model.metric.DependencyDetailsMetric
+import io.github.janbarari.gradle.core.UseCaseNoInput
+
+class CreateDependencyDetailsMetricUseCase(
+ private val thirdPartyDependencies: List
+) : UseCaseNoInput() {
+
+ override suspend fun execute(): DependencyDetailsMetric {
+ return DependencyDetailsMetric(
+ dependencies = thirdPartyDependencies
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/render/CreateDependencyDetailsReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/render/CreateDependencyDetailsReportStage.kt
new file mode 100644
index 00000000..039d4258
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/render/CreateDependencyDetailsReportStage.kt
@@ -0,0 +1,46 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencydetails.render
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.DependencyDetailsReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.whenNotNull
+
+class CreateDependencyDetailsReportStage(
+ private val metrics: List
+): Stage {
+
+ override suspend fun process(input: Report): Report {
+ return input.apply {
+ metrics.last().dependencyDetailsMetric.whenNotNull {
+ dependencyDetailsReport = DependencyDetailsReport(
+ dependencies = dependencies,
+ cumulativeDependenciesSizeByKb = dependencies.sumOf { it.sizeByKb }
+ )
+ }
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/render/RenderDependencyDetailsReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/render/RenderDependencyDetailsReportStage.kt
new file mode 100644
index 00000000..e1efd632
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/render/RenderDependencyDetailsReportStage.kt
@@ -0,0 +1,91 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencydetails.render
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.toArrayString
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+
+class RenderDependencyDetailsReportStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val DEPENDENCY_DETAILS_METRIC_TEMPLATE_ID = "%dependency-details-metric%"
+ private const val DEPENDENCY_DETAILS_METRIC_TEMPLATE_FILE_NAME = "dependency-details-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.dependencyDetailsReport.isNull()) return input.replace(
+ DEPENDENCY_DETAILS_METRIC_TEMPLATE_ID, getEmptyRender()
+ )
+
+ return input.replace(DEPENDENCY_DETAILS_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Dependency Details is not available!")
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(DEPENDENCY_DETAILS_METRIC_TEMPLATE_FILE_NAME)
+ report.dependencyDetailsReport.whenNotNull {
+ val chartLabels = mutableListOf()
+ val chartDataset = mutableListOf()
+ dependencies.whenEach {
+ chartLabels.add("$moduleGroup:$moduleName")
+ chartDataset.add(sizeByKb)
+ }
+
+ val tableDataset = buildString {
+ dependencies
+ .filter { it.sizeByKb > 0 }
+ .sortedByDescending { it.sizeByKb }
+ .forEachIndexed { index, dependency ->
+ append("")
+ append("${index + 1} | ")
+ append("${dependency.name} | ")
+ append("${dependency.sizeByKb}kb | ")
+ append("
")
+ }
+ }
+
+ renderedTemplate = if (chartDataset.sum() > 1000) {
+ renderedTemplate.replace("%cumulative-dependencies-size%", "%sMb".format((chartDataset.sum() / 1024)))
+ } else {
+ renderedTemplate.replace("%cumulative-dependencies-size%", "%skb".format(chartDataset.sum()))
+ }
+
+ renderedTemplate = renderedTemplate
+ .replace("%table-dataset%", tableDataset)
+ .replace("%chart-labels%", chartLabels.toArrayString())
+ .replace("%chart-dataset%", chartDataset.toString())
+ }
+ return renderedTemplate
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/update/UpdateDependencyDetailsMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/update/UpdateDependencyDetailsMetricStage.kt
new file mode 100644
index 00000000..c8d4f725
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/update/UpdateDependencyDetailsMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencydetails.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateDependencyDetailsMetricStage(
+ private val updateDependencyDetailsMetricUseCase: UpdateDependencyDetailsMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ dependencyDetailsMetric = updateDependencyDetailsMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/update/UpdateDependencyDetailsMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/update/UpdateDependencyDetailsMetricUseCase.kt
new file mode 100644
index 00000000..dc409475
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencydetails/update/UpdateDependencyDetailsMetricUseCase.kt
@@ -0,0 +1,37 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencydetails.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.DependencyDetailsMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+
+class UpdateDependencyDetailsMetricUseCase(
+ private val repo: DatabaseRepository
+): UseCaseNoInput() {
+
+ override suspend fun execute(): DependencyDetailsMetric {
+ return repo.getTemporaryMetrics().last().dependencyDetailsMetric!!
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/create/CreateDependencyResolveProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/create/CreateDependencyResolveProcessMetricStage.kt
new file mode 100644
index 00000000..b1fac293
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/create/CreateDependencyResolveProcessMetricStage.kt
@@ -0,0 +1,43 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencyresolveprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateDependencyResolveProcessMetricStage(
+ private val buildInfo: BuildInfo,
+ private val createDependencyResolveProcessMetricUseCase: CreateDependencyResolveProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ if (buildInfo.isSuccessful) {
+ dependencyResolveProcessMetric = createDependencyResolveProcessMetricUseCase.execute(buildInfo)
+ }
+ }
+ }
+
+}
+
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/create/CreateDependencyResolveProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/create/CreateDependencyResolveProcessMetricUseCase.kt
new file mode 100644
index 00000000..cd37cdd5
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/create/CreateDependencyResolveProcessMetricUseCase.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencyresolveprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.DependencyResolveProcessMetric
+import io.github.janbarari.gradle.core.UseCase
+
+class CreateDependencyResolveProcessMetricUseCase: UseCase() {
+
+ override suspend fun execute(input: BuildInfo): DependencyResolveProcessMetric {
+ return DependencyResolveProcessMetric(
+ median = input.getTotalDependenciesResolveDuration().toMillis(),
+ mean = input.getTotalDependenciesResolveDuration().toMillis()
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/report/CreateDependencyResolveProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/report/CreateDependencyResolveProcessReportStage.kt
new file mode 100644
index 00000000..379a984a
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/report/CreateDependencyResolveProcessReportStage.kt
@@ -0,0 +1,68 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencyresolveprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.DependencyResolveProcessReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isBiggerEquals
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.mapToDependencyResolveMeanTimespanChartPoints
+import io.github.janbarari.gradle.extension.mapToDependencyResolveMedianTimespanChartPoints
+import io.github.janbarari.gradle.extension.whenEmpty
+
+class CreateDependencyResolveProcessReportStage(
+ private val metrics: List
+) : Stage {
+
+ companion object {
+ private const val SKIP_THRESHOLD_IN_MS = 50L
+ }
+
+ override suspend fun process(input: Report): Report {
+ val medianChartPoints = metrics.filter { metric ->
+ metric.dependencyResolveProcessMetric.isNotNull() &&
+ metric.dependencyResolveProcessMetric?.median?.isBiggerEquals(SKIP_THRESHOLD_IN_MS) ?: false
+ }.mapToDependencyResolveMedianTimespanChartPoints()
+ .whenEmpty {
+ return input
+ }
+
+ val meanChartPoints = metrics.filter { metric ->
+ metric.dependencyResolveProcessMetric.isNotNull() &&
+ metric.dependencyResolveProcessMetric?.mean?.isBiggerEquals(SKIP_THRESHOLD_IN_MS) ?: false
+ }.mapToDependencyResolveMeanTimespanChartPoints()
+ .whenEmpty {
+ return input
+ }
+
+ return input.apply {
+ dependencyResolveProcessReport = DependencyResolveProcessReport(
+ medianValues = medianChartPoints,
+ meanValues = meanChartPoints,
+ )
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/report/RenderDependencyResolveProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/report/RenderDependencyResolveProcessReportStage.kt
new file mode 100644
index 00000000..5bbbb74a
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/report/RenderDependencyResolveProcessReportStage.kt
@@ -0,0 +1,102 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencyresolveprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.mapToChartPoints
+import io.github.janbarari.gradle.extension.maxValue
+import io.github.janbarari.gradle.extension.minValue
+import io.github.janbarari.gradle.extension.minimize
+import io.github.janbarari.gradle.extension.toArrayString
+import io.github.janbarari.gradle.extension.toIntList
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+import io.github.janbarari.gradle.utils.MathUtils
+
+/**
+ * Generates html result for [io.github.janbarari.gradle.analytics.domain.model.report.DependencyResolveProcessReport].
+ */
+class RenderDependencyResolveProcessReportStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val CHART_MAX_COLUMNS = 12
+ private const val CHART_SUGGESTED_MIN_MAX_PERCENTAGE = 30
+ private const val DEPENDENCY_RESOLVE_METRIC_TEMPLATE_ID = "%dependency-resolve-process-metric%"
+ private const val DEPENDENCY_RESOLVE_METRIC_TEMPLATE_FILE_NAME = "dependency-resolve-process-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.dependencyResolveProcessReport.isNull()) {
+ return input.replace(DEPENDENCY_RESOLVE_METRIC_TEMPLATE_ID, getEmptyRender())
+ }
+
+ return input.replace(DEPENDENCY_RESOLVE_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(DEPENDENCY_RESOLVE_METRIC_TEMPLATE_FILE_NAME)
+ report.dependencyResolveProcessReport.whenNotNull {
+ val medianChartValues = medianValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ val meanChartValues = meanValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ val chartLabels = medianValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.description }
+ .toArrayString()
+
+ val maximumValue = Math.max(medianValues.maxValue(), meanValues.maxValue())
+ val minimumValue = Math.min(medianValues.minValue(), meanValues.minValue())
+ val chartSuggestedMaxValue = MathUtils.sumWithPercentage(maximumValue, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+ val chartSuggestedMinValue = MathUtils.deductWithPercentage(minimumValue, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+
+ renderedTemplate = renderedTemplate
+ .replace("%suggested-max-value%", chartSuggestedMaxValue.toString())
+ .replace("%suggested-min-value%", chartSuggestedMinValue.toString())
+ .replace("%chart-median-values%", medianChartValues)
+ .replace("%chart-mean-values%", meanChartValues)
+ .replace("%chart-labels%", chartLabels)
+ }
+ return renderedTemplate
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Dependency Resolve Process is not available!")
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/update/UpdateDependencyResolveProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/update/UpdateDependencyResolveProcessMetricStage.kt
new file mode 100644
index 00000000..a975e44f
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/update/UpdateDependencyResolveProcessMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencyresolveprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateDependencyResolveProcessMetricStage(
+ private val updateDependencyResolveProcessMetricUseCase: UpdateDependencyResolveProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ dependencyResolveProcessMetric = updateDependencyResolveProcessMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/update/UpdateDependencyResolveProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/update/UpdateDependencyResolveProcessMetricUseCase.kt
new file mode 100644
index 00000000..3d227899
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/dependencyresolveprocess/update/UpdateDependencyResolveProcessMetricUseCase.kt
@@ -0,0 +1,66 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.dependencyresolveprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.DependencyResolveProcessMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.isBiggerEquals
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.extension.whenTrue
+import io.github.janbarari.gradle.utils.MathUtils
+
+/**
+ * Generates a new metric with Median mathematics based on temporary metrics.
+ */
+class UpdateDependencyResolveProcessMetricUseCase(
+ private val repo: DatabaseRepository
+): UseCaseNoInput() {
+
+ companion object {
+ private const val SKIP_THRESHOLD_IN_MS = 50L
+ }
+
+ override suspend fun execute(): DependencyResolveProcessMetric {
+ val medianValues = mutableListOf()
+ val meanValues = mutableListOf()
+ repo.getTemporaryMetrics().whenEach {
+ dependencyResolveProcessMetric.whenNotNull {
+ // In order to have accurate metric, don't add metric value in Median dataset if it's under 50 milliseconds.
+ median.isBiggerEquals(SKIP_THRESHOLD_IN_MS).whenTrue {
+ medianValues.add(median)
+ }
+ mean.isBiggerEquals(SKIP_THRESHOLD_IN_MS).whenTrue {
+ meanValues.add(mean)
+ }
+ }
+ }
+
+ return DependencyResolveProcessMetric(
+ median = MathUtils.longMedian(medianValues),
+ mean = MathUtils.longMean(meanValues)
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/create/CreateExecutionProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/create/CreateExecutionProcessMetricStage.kt
new file mode 100644
index 00000000..5d0adb6b
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/create/CreateExecutionProcessMetricStage.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.executionprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateExecutionProcessMetricStage(
+ private val buildInfo: BuildInfo,
+ private val createExecutionProcessMetricUseCase: CreateExecutionProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ if (buildInfo.isSuccessful) {
+ executionProcessMetric = createExecutionProcessMetricUseCase.execute(buildInfo)
+ }
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/create/CreateExecutionProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/create/CreateExecutionProcessMetricUseCase.kt
new file mode 100644
index 00000000..ca6424cb
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/create/CreateExecutionProcessMetricUseCase.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.executionprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.ExecutionProcessMetric
+import io.github.janbarari.gradle.core.UseCase
+
+class CreateExecutionProcessMetricUseCase: UseCase() {
+
+ override suspend fun execute(input: BuildInfo): ExecutionProcessMetric {
+ return ExecutionProcessMetric(
+ median = input.getExecutionDuration().toMillis(),
+ mean = input.getExecutionDuration().toMillis()
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/report/CreateExecutionProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/report/CreateExecutionProcessReportStage.kt
new file mode 100644
index 00000000..f742baca
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/report/CreateExecutionProcessReportStage.kt
@@ -0,0 +1,67 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.executionprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ExecutionProcessReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isBiggerEquals
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.mapToExecutionMeanTimespanChartPoints
+import io.github.janbarari.gradle.extension.mapToExecutionMedianTimespanChartPoints
+import io.github.janbarari.gradle.extension.whenEmpty
+
+class CreateExecutionProcessReportStage(
+ private val metrics: List
+) : Stage {
+
+ companion object {
+ private const val SKIP_THRESHOLD_IN_MS = 50L
+ }
+
+ override suspend fun process(input: Report): Report {
+ val medianChartPoints = metrics.filter { metric ->
+ metric.executionProcessMetric.isNotNull() &&
+ metric.executionProcessMetric?.median?.isBiggerEquals(SKIP_THRESHOLD_IN_MS) ?: false
+ }.mapToExecutionMedianTimespanChartPoints()
+ .whenEmpty {
+ return input
+ }
+
+ val meanChartPoints = metrics.filter { metric ->
+ metric.executionProcessMetric.isNotNull() &&
+ metric.executionProcessMetric?.mean?.isBiggerEquals(SKIP_THRESHOLD_IN_MS) ?: false
+ }.mapToExecutionMeanTimespanChartPoints()
+ .whenEmpty {
+ return input
+ }
+
+ return input.apply {
+ executionProcessReport = ExecutionProcessReport(
+ medianValues = medianChartPoints,
+ meanValues = meanChartPoints,
+ )
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/report/RenderExecutionProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/report/RenderExecutionProcessReportStage.kt
new file mode 100644
index 00000000..a251ee3c
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/report/RenderExecutionProcessReportStage.kt
@@ -0,0 +1,98 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.executionprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.mapToChartPoints
+import io.github.janbarari.gradle.extension.maxValue
+import io.github.janbarari.gradle.extension.minValue
+import io.github.janbarari.gradle.extension.minimize
+import io.github.janbarari.gradle.extension.toArrayString
+import io.github.janbarari.gradle.extension.toIntList
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+import io.github.janbarari.gradle.utils.MathUtils
+
+class RenderExecutionProcessReportStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val CHART_MAX_COLUMNS = 12
+ private const val CHART_SUGGESTED_MIN_MAX_PERCENTAGE = 30
+ private const val EXECUTION_METRIC_TEMPLATE_ID = "%execution-process-metric%"
+ private const val EXECUTION_METRIC_TEMPLATE_FILE_NAME = "execution-process-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.executionProcessReport.isNull())
+ return input.replace(EXECUTION_METRIC_TEMPLATE_ID, getEmptyRender())
+
+ return input.replace(EXECUTION_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Execution Process is not available!")
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(EXECUTION_METRIC_TEMPLATE_FILE_NAME)
+ report.executionProcessReport.whenNotNull {
+ val medianChartValues = medianValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ val meanChartValues = meanValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ val chartLabels = medianValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.description }
+ .toArrayString()
+
+ val maximumValue = Math.max(medianValues.maxValue(), meanValues.maxValue())
+ val minimumValue = Math.min(medianValues.minValue(), meanValues.minValue())
+ val chartSuggestedMaxValue = MathUtils.sumWithPercentage(maximumValue, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+ val chartSuggestedMinValue = MathUtils.deductWithPercentage(minimumValue, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+
+ renderedTemplate = renderedTemplate
+ .replace("%suggested-max-value%", chartSuggestedMaxValue.toString())
+ .replace("%suggested-min-value%", chartSuggestedMinValue.toString())
+ .replace("%chart-median-values%", medianChartValues)
+ .replace("%chart-mean-values%", meanChartValues)
+ .replace("%chart-labels%", chartLabels)
+ }
+ return renderedTemplate
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/update/UpdateExecutionProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/update/UpdateExecutionProcessMetricStage.kt
new file mode 100644
index 00000000..1b5dddf7
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/update/UpdateExecutionProcessMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.executionprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateExecutionProcessMetricStage(
+ private val updateExecutionProcessMetricUseCase: UpdateExecutionProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ executionProcessMetric = updateExecutionProcessMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/update/UpdateExecutionProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/update/UpdateExecutionProcessMetricUseCase.kt
new file mode 100644
index 00000000..a7700d43
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/executionprocess/update/UpdateExecutionProcessMetricUseCase.kt
@@ -0,0 +1,63 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.executionprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.ExecutionProcessMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.isBiggerEquals
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.extension.whenTrue
+import io.github.janbarari.gradle.utils.MathUtils
+
+class UpdateExecutionProcessMetricUseCase(
+ private val repo: DatabaseRepository
+): UseCaseNoInput() {
+
+ companion object {
+ private const val SKIP_THRESHOLD_IN_MS = 50L
+ }
+
+ override suspend fun execute(): ExecutionProcessMetric {
+ val medianValues = mutableListOf()
+ val meanValues = mutableListOf()
+ repo.getTemporaryMetrics().whenEach {
+ executionProcessMetric.whenNotNull {
+ // In order to have accurate metric, don't add metric value in Median dataset if it's under 50 milliseconds.
+ median.isBiggerEquals(SKIP_THRESHOLD_IN_MS).whenTrue {
+ medianValues.add(median)
+ }
+ mean.isBiggerEquals(SKIP_THRESHOLD_IN_MS).whenTrue {
+ meanValues.add(mean)
+ }
+ }
+ }
+
+ return ExecutionProcessMetric(
+ median = MathUtils.longMedian(medianValues),
+ mean = MathUtils.longMean(meanValues)
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/create/CreateInitializationProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/create/CreateInitializationProcessMetricStage.kt
new file mode 100644
index 00000000..b7005a2c
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/create/CreateInitializationProcessMetricStage.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.initializationprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateInitializationProcessMetricStage(
+ private val buildInfo: BuildInfo,
+ private val createInitializationProcessMetricUseCase: CreateInitializationProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ if (buildInfo.isSuccessful) {
+ initializationProcessMetric = createInitializationProcessMetricUseCase.execute(buildInfo)
+ }
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/create/CreateInitializationProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/create/CreateInitializationProcessMetricUseCase.kt
new file mode 100644
index 00000000..d08fe890
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/create/CreateInitializationProcessMetricUseCase.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.initializationprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.core.UseCase
+import io.github.janbarari.gradle.analytics.domain.model.metric.InitializationProcessMetric
+
+class CreateInitializationProcessMetricUseCase: UseCase() {
+
+ override suspend fun execute(input: BuildInfo): InitializationProcessMetric {
+ return InitializationProcessMetric(
+ median = input.getInitializationDuration().toMillis(),
+ mean = input.getInitializationDuration().toMillis()
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/report/CreateInitializationProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/report/CreateInitializationProcessReportStage.kt
new file mode 100644
index 00000000..a08ba3de
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/report/CreateInitializationProcessReportStage.kt
@@ -0,0 +1,68 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.initializationprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.InitializationProcessReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isBiggerEquals
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.mapToInitializationMeanTimespanChartPoints
+import io.github.janbarari.gradle.extension.mapToInitializationMedianTimespanChartPoints
+import io.github.janbarari.gradle.extension.whenEmpty
+
+class CreateInitializationProcessReportStage(
+ private val metrics: List
+) : Stage {
+
+ companion object {
+ private const val SKIP_THRESHOLD_IN_MS = 50L
+ }
+
+ override suspend fun process(input: Report): Report {
+ val medianChartPoints = metrics.filter { metric ->
+ metric.initializationProcessMetric.isNotNull() &&
+ metric.initializationProcessMetric?.median?.isBiggerEquals(SKIP_THRESHOLD_IN_MS) ?: false
+ }.mapToInitializationMedianTimespanChartPoints()
+ .whenEmpty {
+ return input
+ }
+
+ val meanChartPoints = metrics.filter { metric ->
+ metric.initializationProcessMetric.isNotNull() &&
+ metric.initializationProcessMetric?.mean?.isBiggerEquals(SKIP_THRESHOLD_IN_MS) ?: false
+ }.mapToInitializationMeanTimespanChartPoints()
+ .whenEmpty {
+ return input
+ }
+
+ return input.apply {
+ initializationProcessReport = InitializationProcessReport(
+ medianValues = medianChartPoints,
+ meanValues = meanChartPoints,
+ )
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/report/RenderInitializationProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/report/RenderInitializationProcessReportStage.kt
new file mode 100644
index 00000000..02bee91b
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/report/RenderInitializationProcessReportStage.kt
@@ -0,0 +1,98 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.initializationprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.mapToChartPoints
+import io.github.janbarari.gradle.extension.maxValue
+import io.github.janbarari.gradle.extension.minValue
+import io.github.janbarari.gradle.extension.minimize
+import io.github.janbarari.gradle.extension.toArrayString
+import io.github.janbarari.gradle.extension.toIntList
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+import io.github.janbarari.gradle.utils.MathUtils
+
+class RenderInitializationProcessReportStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val CHART_MAX_COLUMNS = 12
+ private const val CHART_SUGGESTED_MIN_MAX_PERCENTAGE = 30
+ private const val INITIALIZATION_METRIC_TEMPLATE_ID = "%initialization-process-metric%"
+ private const val INITIALIZATION_METRIC_TEMPLATE_FILE_NAME = "initialization-process-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.initializationProcessReport.isNull())
+ return input.replace(INITIALIZATION_METRIC_TEMPLATE_ID, getEmptyRender())
+
+ return input.replace(INITIALIZATION_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Initialization Process is not available!")
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(INITIALIZATION_METRIC_TEMPLATE_FILE_NAME)
+ report.initializationProcessReport.whenNotNull {
+ val medianChartValues = medianValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ val meanChartValues = meanValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.value }
+ .toIntList()
+ .toString()
+
+ val chartLabels = medianValues
+ .minimize(CHART_MAX_COLUMNS)
+ .mapToChartPoints()
+ .map { it.description }
+ .toArrayString()
+
+ val maximumValue = Math.max(medianValues.maxValue(), meanValues.maxValue())
+ val minimumValue = Math.min(medianValues.minValue(), meanValues.minValue())
+ val chartSuggestedMaxValue = MathUtils.sumWithPercentage(maximumValue, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+ val chartSuggestedMinValue = MathUtils.deductWithPercentage(minimumValue, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+
+ renderedTemplate = renderedTemplate
+ .replace("%suggested-max-value%", chartSuggestedMaxValue.toString())
+ .replace("%suggested-min-value%", chartSuggestedMinValue.toString())
+ .replace("%chart-median-values%", medianChartValues)
+ .replace("%chart-mean-values%", meanChartValues)
+ .replace("%chart-labels%", chartLabels)
+ }
+ return renderedTemplate
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/update/UpdateInitializationProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/update/UpdateInitializationProcessMetricStage.kt
new file mode 100644
index 00000000..e2967ce1
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/update/UpdateInitializationProcessMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.initializationprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateInitializationProcessMetricStage(
+ private val updateInitializationProcessMetricUseCase: UpdateInitializationProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ initializationProcessMetric = updateInitializationProcessMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/update/UpdateInitializationProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/update/UpdateInitializationProcessMetricUseCase.kt
new file mode 100644
index 00000000..ac5591b6
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/initializationprocess/update/UpdateInitializationProcessMetricUseCase.kt
@@ -0,0 +1,63 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.initializationprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.InitializationProcessMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.isBiggerEquals
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.extension.whenTrue
+import io.github.janbarari.gradle.utils.MathUtils
+
+class UpdateInitializationProcessMetricUseCase(
+ private val repo: DatabaseRepository
+) : UseCaseNoInput() {
+
+ companion object {
+ private const val SKIP_THRESHOLD_IN_MS = 50L
+ }
+
+ override suspend fun execute(): InitializationProcessMetric {
+ val medianValues = mutableListOf()
+ val meanValues = mutableListOf()
+ repo.getTemporaryMetrics().whenEach {
+ initializationProcessMetric.whenNotNull {
+ // In order to have accurate metric, don't add metric value in Median dataset if it's under 50 milliseconds.
+ median.isBiggerEquals(SKIP_THRESHOLD_IN_MS).whenTrue {
+ medianValues.add(median)
+ }
+ mean.isBiggerEquals(SKIP_THRESHOLD_IN_MS).whenTrue {
+ meanValues.add(mean)
+ }
+ }
+ }
+
+ return InitializationProcessMetric(
+ median = MathUtils.longMedian(medianValues),
+ mean = MathUtils.longMean(meanValues)
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/create/CreateModulesBuildHeatmapMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/create/CreateModulesBuildHeatmapMetricStage.kt
new file mode 100644
index 00000000..d633c12f
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/create/CreateModulesBuildHeatmapMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesbuildheatmap.create
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateModulesBuildHeatmapMetricStage(
+ private val createModulesBuildHeatmapMetricUseCase: CreateModulesBuildHeatmapMetricUseCase
+) : Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesBuildHeatmap = createModulesBuildHeatmapMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/create/CreateModulesBuildHeatmapMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/create/CreateModulesBuildHeatmapMetricUseCase.kt
new file mode 100644
index 00000000..64876174
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/create/CreateModulesBuildHeatmapMetricUseCase.kt
@@ -0,0 +1,55 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesbuildheatmap.create
+
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.ModulesDependencyGraph
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModuleBuildHeatmap
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesBuildHeatmapMetric
+import io.github.janbarari.gradle.core.UseCase
+import io.github.janbarari.gradle.core.UseCaseNoInput
+
+class CreateModulesBuildHeatmapMetricUseCase(
+ private val modules: List,
+ private val modulesDependencyGraph: ModulesDependencyGraph
+): UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesBuildHeatmapMetric {
+ val result = mutableListOf()
+
+ modules.forEach { module ->
+ val dependantModulesCount = modulesDependencyGraph.dependencies.filter { it.dependency == module.path }.size
+ result.add(
+ ModuleBuildHeatmap(
+ path = module.path,
+ dependantModulesCount = dependantModulesCount
+ )
+ )
+ }
+
+ return ModulesBuildHeatmapMetric(
+ modules = result
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/render/CreateModulesBuildHeatmapReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/render/CreateModulesBuildHeatmapReportStage.kt
new file mode 100644
index 00000000..42810780
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/render/CreateModulesBuildHeatmapReportStage.kt
@@ -0,0 +1,82 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesbuildheatmap.render
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ModuleBuildHeatmap
+import io.github.janbarari.gradle.analytics.domain.model.report.ModulesBuildHeatmapReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.MathUtils
+
+class CreateModulesBuildHeatmapReportStage(
+ private val metrics: List
+) : Stage {
+
+ override suspend fun process(input: Report): Report {
+ val temp = mutableListOf()
+
+ metrics.last().modulesBuildHeatmap.whenNotNull {
+ modules.forEach { module ->
+ temp.add(
+ ModuleBuildHeatmap(
+ path = module.path,
+ dependantModulesCount = module.dependantModulesCount,
+ avgMedianCacheHit = getAvgMeanCacheHit(module.path),
+ totalBuildCount = getModuleTotalBuildCount(module.path)
+ )
+ )
+ }
+ }
+
+ return input.apply {
+ modulesBuildHeatmapReport = ModulesBuildHeatmapReport(
+ modules = temp
+ )
+ }
+ }
+
+ fun getAvgMeanCacheHit(path: String): Long {
+ val hits = mutableListOf()
+ metrics.filter {
+ it.cacheHitMetric.isNotNull()
+ }.whenEach {
+ cacheHitMetric!!.modules.filter { moduleCacheHit ->
+ moduleCacheHit.path == path
+ }.whenEach {
+ hits.add(rate)
+ }
+ }
+ return MathUtils.longMean(hits)
+ }
+
+ fun getModuleTotalBuildCount(path: String): Int {
+ return metrics.filter {
+ it.modulesBuildHeatmap.isNotNull() && it.modulesBuildHeatmap!!.modules.any { module -> module.path == path }
+ }.size
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/render/RenderModulesBuildHeatmapReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/render/RenderModulesBuildHeatmapReportStage.kt
new file mode 100644
index 00000000..22644218
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/render/RenderModulesBuildHeatmapReportStage.kt
@@ -0,0 +1,86 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesbuildheatmap.render
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.toArrayString
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+import io.github.janbarari.gradle.utils.MathUtils
+
+class RenderModulesBuildHeatmapReportStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val MODULES_BUILD_HEATMAP_TEMPLATE_ID = "%modules-build-heatmap-metric%"
+ private const val MODULES_BUILD_HEATMAP_TEMPLATE_FILE_NAME = "modules-build-heatmap-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.modulesBuildHeatmapReport.isNull())
+ return input.replace(MODULES_BUILD_HEATMAP_TEMPLATE_ID, getEmptyRender())
+
+ return input.replace(MODULES_BUILD_HEATMAP_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Modules Build Heatmap is not available!")
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(MODULES_BUILD_HEATMAP_TEMPLATE_FILE_NAME)
+ report.modulesBuildHeatmapReport.whenNotNull {
+
+ val labels = mutableListOf()
+ val data = mutableListOf()
+ val colors = mutableListOf()
+
+ modules.sortedByDescending { it.dependantModulesCount }.forEach { module ->
+ labels.add("${module.path} | ${module.dependantModulesCount}D")
+ colors.add(getColor(module.dependantModulesCount))
+ data.add(MathUtils.deductWithPercentage(module.totalBuildCount.toLong(), module.avgMedianCacheHit.toInt()))
+ }
+
+ val chartHeight = modules.size * 36
+
+ renderedTemplate = renderedTemplate
+ .replace("%labels%", labels.toArrayString())
+ .replace("%data%", data.toString())
+ .replace("%colors%", colors.toArrayString())
+ .replace("%chart-height%", "${chartHeight}px")
+ }
+ return renderedTemplate
+ }
+
+ fun getColor(dependantModulesCount: Int): String {
+ return if (dependantModulesCount > 6) "#d73027"
+ else if (dependantModulesCount in 5..6) "#fdae61"
+ else if (dependantModulesCount in 3..4) "#ffffbf"
+ else if (dependantModulesCount in 1..2) "#abd9e9"
+ else "#4575b4"
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/update/UpdateModulesBuildHeatmapMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/update/UpdateModulesBuildHeatmapMetricStage.kt
new file mode 100644
index 00000000..f4508683
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/update/UpdateModulesBuildHeatmapMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesbuildheatmap.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateModulesBuildHeatmapMetricStage(
+ private val updateModulesBuildHeatmapMetricUseCase: UpdateModulesBuildHeatmapMetricUseCase
+) : Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesBuildHeatmap = updateModulesBuildHeatmapMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/update/UpdateModulesBuildHeatmapMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/update/UpdateModulesBuildHeatmapMetricUseCase.kt
new file mode 100644
index 00000000..190c4774
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesbuildheatmap/update/UpdateModulesBuildHeatmapMetricUseCase.kt
@@ -0,0 +1,39 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesbuildheatmap.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesBuildHeatmapMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+
+class UpdateModulesBuildHeatmapMetricUseCase(
+ private val repo: DatabaseRepository
+) : UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesBuildHeatmapMetric {
+ return ModulesBuildHeatmapMetric(
+ modules = repo.getTemporaryMetrics().last().modulesBuildHeatmap?.modules ?: emptyList()
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/create/CreateModulesCrashCountMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/create/CreateModulesCrashCountMetricStage.kt
new file mode 100644
index 00000000..dc71597e
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/create/CreateModulesCrashCountMetricStage.kt
@@ -0,0 +1,40 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulescrashcount.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateModulesCrashCountMetricStage(
+ private val buildInfo: BuildInfo,
+ private val createModulesCrashCountMetricUseCase: CreateModulesCrashCountMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesCrashCountMetric = createModulesCrashCountMetricUseCase.execute(buildInfo)
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/create/CreateModulesCrashCountMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/create/CreateModulesCrashCountMetricUseCase.kt
new file mode 100644
index 00000000..d6048747
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/create/CreateModulesCrashCountMetricUseCase.kt
@@ -0,0 +1,63 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulescrashcount.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesCrashCountMetric
+import io.github.janbarari.gradle.core.UseCase
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.whenNotNull
+
+class CreateModulesCrashCountMetricUseCase(
+ private val modules: List
+) : UseCase() {
+
+ override suspend fun execute(input: BuildInfo): ModulesCrashCountMetric {
+ val modules = mutableListOf()
+
+ if (!input.isSuccessful && input.failure.isNotNull()) {
+ val findFirstFailedTask = input.executedTasks.sortedBy { it.startedAt }.firstOrNull { !it.isSuccessful }
+
+ findFirstFailedTask.whenNotNull {
+ val module = this@CreateModulesCrashCountMetricUseCase.modules.firstOrNull {
+ it.path == getModule()
+ }
+ module.whenNotNull {
+ modules.add(
+ ModulesCrashCountMetric.ModuleCrash(
+ path = path,
+ totalCrashes = 1
+ )
+ )
+ }
+ }
+
+ }
+
+ return ModulesCrashCountMetric(
+ modules = modules
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/render/CreateModulesCrashCountReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/render/CreateModulesCrashCountReportStage.kt
new file mode 100644
index 00000000..231cc0ed
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/render/CreateModulesCrashCountReportStage.kt
@@ -0,0 +1,65 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulescrashcount.render
+
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesCrashCountMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ModulesCrashCountReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.whenEach
+
+class CreateModulesCrashCountReportStage(
+ private val modules: List,
+ private val metrics: List
+): Stage {
+
+ override suspend fun process(input: Report): Report {
+ val modules = mutableListOf()
+
+ this.modules.whenEach {
+ val crashes = metrics
+ .filter { it.modulesCrashCountMetric.isNotNull() }
+ .sumOf { metric ->
+ metric.modulesCrashCountMetric!!.modules
+ .filter { it.path == path }
+ .sumOf { it.totalCrashes }
+ }
+ modules.add(
+ ModulesCrashCountMetric.ModuleCrash(
+ path = path,
+ totalCrashes = crashes
+ )
+ )
+ }
+
+ return input.apply {
+ modulesCrashCountReport = ModulesCrashCountReport(
+ modules = modules
+ )
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/render/RenderModulesCrashCountReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/render/RenderModulesCrashCountReportStage.kt
new file mode 100644
index 00000000..5c9a74d4
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/render/RenderModulesCrashCountReportStage.kt
@@ -0,0 +1,98 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulescrashcount.render
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.toArrayString
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+
+class RenderModulesCrashCountReportStage(
+ private val report: Report
+): Stage {
+
+ companion object {
+ private const val MODULES_CRASH_COUNT_METRIC_TEMPLATE_ID = "%modules-crash-count-metric%"
+ private const val MODULES_CRASH_COUNT_METRIC_TEMPLATE_FILENAME = "modules-crash-count-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.modulesCrashCountReport.isNull())
+ return input.replace(MODULES_CRASH_COUNT_METRIC_TEMPLATE_ID, getEmptyRender())
+
+ return input.replace(MODULES_CRASH_COUNT_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Modules Crash Count is not available!")
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(MODULES_CRASH_COUNT_METRIC_TEMPLATE_FILENAME)
+ report.modulesCrashCountReport.whenNotNull {
+ val labels = mutableListOf()
+ val colors = mutableListOf()
+ val dataset = mutableListOf()
+
+ modules.sortedByDescending { it.totalCrashes }
+ .whenEach {
+ labels.add(path)
+ colors.add(getRandomColor())
+ dataset.add(totalCrashes)
+ }
+
+ val chartHeight = dataset.size * 36
+
+ renderedTemplate = renderedTemplate
+ .replace("%labels%", labels.toArrayString())
+ .replace("%colors%", colors.toArrayString())
+ .replace("%dataset%", dataset.toString())
+ .replace("%chart-height%", "${chartHeight}px")
+ }
+ return renderedTemplate
+ }
+
+ fun getRandomColor(): String {
+ val colors = listOf(
+ "#3b76af",
+ "#b3c6e5",
+ "#ef8536",
+ "#f5bd82",
+ "#519d3e",
+ "#a8dc93",
+ "#c53a32",
+ "#f19d99",
+ "#8d6ab8",
+ "#c2b1d2",
+ "#84584e",
+ "#be9e96",
+ "#d57ebe",
+ "#c2cd30"
+ )
+ return colors[colors.indices.random() % colors.size]
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/update/UpdateModulesCrashCountMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/update/UpdateModulesCrashCountMetricStage.kt
new file mode 100644
index 00000000..b1e16855
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/update/UpdateModulesCrashCountMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulescrashcount.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateModulesCrashCountMetricStage(
+ private val updateModulesCrashCountMetricUseCase: UpdateModulesCrashCountMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesCrashCountMetric = updateModulesCrashCountMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/update/UpdateModulesCrashCountMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/update/UpdateModulesCrashCountMetricUseCase.kt
new file mode 100644
index 00000000..ee694d7b
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulescrashcount/update/UpdateModulesCrashCountMetricUseCase.kt
@@ -0,0 +1,61 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulescrashcount.update
+
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesCrashCountMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.whenEach
+
+class UpdateModulesCrashCountMetricUseCase(
+ private val repo: DatabaseRepository,
+ private val modules: List
+): UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesCrashCountMetric {
+ val modules = mutableListOf()
+
+ this.modules.whenEach {
+ val crashes = repo.getTemporaryMetrics()
+ .filter { it.modulesCrashCountMetric.isNotNull() }
+ .sumOf { metric ->
+ metric.modulesCrashCountMetric!!.modules
+ .filter { it.path == path }
+ .sumOf { it.totalCrashes }
+ }
+ modules.add(
+ ModulesCrashCountMetric.ModuleCrash(
+ path = path,
+ totalCrashes = crashes
+ )
+ )
+ }
+
+ return ModulesCrashCountMetric(
+ modules = modules
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/create/CreateModulesDependencyGraphMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/create/CreateModulesDependencyGraphMetricStage.kt
new file mode 100644
index 00000000..a168bf57
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/create/CreateModulesDependencyGraphMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesdependencygraph.create
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateModulesDependencyGraphMetricStage(
+ private val createModulesDependencyGraphMetricUseCase: CreateModulesDependencyGraphMetricUseCase
+) : Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesDependencyGraphMetric = createModulesDependencyGraphMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/create/CreateModulesDependencyGraphMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/create/CreateModulesDependencyGraphMetricUseCase.kt
new file mode 100644
index 00000000..584cdc1d
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/create/CreateModulesDependencyGraphMetricUseCase.kt
@@ -0,0 +1,39 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesdependencygraph.create
+
+import io.github.janbarari.gradle.analytics.domain.model.ModulesDependencyGraph
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesDependencyGraphMetric
+import io.github.janbarari.gradle.core.UseCaseNoInput
+
+class CreateModulesDependencyGraphMetricUseCase(
+ private val modulesDependencyGraph: ModulesDependencyGraph
+) : UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesDependencyGraphMetric {
+ return ModulesDependencyGraphMetric(
+ dependencies = modulesDependencyGraph.dependencies
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/report/CreateModulesDependencyGraphReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/report/CreateModulesDependencyGraphReportStage.kt
new file mode 100644
index 00000000..099fdc36
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/report/CreateModulesDependencyGraphReportStage.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesdependencygraph.report
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ModulesDependencyGraphReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+
+class CreateModulesDependencyGraphReportStage(
+ private val metrics: List
+): Stage {
+
+ override suspend fun process(input: Report): Report {
+ return input.apply {
+ modulesDependencyGraphReport = ModulesDependencyGraphReport(
+ dependencies = metrics.last().modulesDependencyGraphMetric?.dependencies ?: emptyList()
+ )
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/report/RenderModulesDependencyGraphReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/report/RenderModulesDependencyGraphReportStage.kt
new file mode 100644
index 00000000..6cfdedae
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/report/RenderModulesDependencyGraphReportStage.kt
@@ -0,0 +1,87 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesdependencygraph.report
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+
+class RenderModulesDependencyGraphReportStage(
+ private val report: Report
+): Stage {
+
+ companion object {
+ private const val MODULES_DEPENDENCY_GRAPH_METRIC_TEMPLATE_ID = "%modules-dependency-graph-metric%"
+ private const val MODULES_DEPENDENCY_GRAPH_METRIC_TEMPLATE_FILE_NAME = "modules-dependency-graph-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.modulesDependencyGraphReport.isNull()) {
+ return input.replace(MODULES_DEPENDENCY_GRAPH_METRIC_TEMPLATE_ID, getEmptyRender())
+ }
+
+ return input.replace(MODULES_DEPENDENCY_GRAPH_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Modules Dependency Graph is not available!")
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(MODULES_DEPENDENCY_GRAPH_METRIC_TEMPLATE_FILE_NAME)
+ report.modulesDependencyGraphReport.whenNotNull {
+ val mermaidCommands = buildString {
+ appendLine()
+ dependencies.whenEach {
+ val type = when(configuration) {
+ "api" -> "api"
+ "implementation" -> "impl"
+ else -> configuration
+ }
+
+ val pathColor = dependencies.filter { it.dependency == dependency }.size
+ var heatmapColor = ":::blue"
+ if (pathColor in 3 .. 4) {
+ heatmapColor = ":::yellow"
+ } else if (pathColor in 5 .. 6) {
+ heatmapColor = ":::orange"
+ } else if (pathColor > 6) {
+ heatmapColor = ":::red"
+ }
+
+ append("\t$path ---> |$type| $dependency$heatmapColor")
+ appendLine()
+ }
+
+ }
+
+ renderedTemplate = renderedTemplate
+ .replace("%mermaid-commands%", mermaidCommands)
+ }
+ return renderedTemplate
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/update/UpdateModulesDependencyGraphMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/update/UpdateModulesDependencyGraphMetricStage.kt
new file mode 100644
index 00000000..9b3c82e7
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/update/UpdateModulesDependencyGraphMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesdependencygraph.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateModulesDependencyGraphMetricStage(
+ private val updateModulesDependencyGraphMetricUseCase: UpdateModulesDependencyGraphMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesDependencyGraphMetric = updateModulesDependencyGraphMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/update/UpdateModulesDependencyGraphMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/update/UpdateModulesDependencyGraphMetricUseCase.kt
new file mode 100644
index 00000000..8dde2dd1
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesdependencygraph/update/UpdateModulesDependencyGraphMetricUseCase.kt
@@ -0,0 +1,39 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesdependencygraph.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesDependencyGraphMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+
+class UpdateModulesDependencyGraphMetricUseCase(
+ private val repo: DatabaseRepository
+) : UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesDependencyGraphMetric {
+ return ModulesDependencyGraphMetric(
+ dependencies = repo.getTemporaryMetrics().last().modulesDependencyGraphMetric?.dependencies ?: emptyList()
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/create/CreateModulesExecutionProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/create/CreateModulesExecutionProcessMetricStage.kt
new file mode 100644
index 00000000..23035039
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/create/CreateModulesExecutionProcessMetricStage.kt
@@ -0,0 +1,42 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesexecutionprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateModulesExecutionProcessMetricStage(
+ private val buildInfo: BuildInfo,
+ private val createModulesExecutionProcessMetricUseCase: CreateModulesExecutionProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ if (buildInfo.isSuccessful) {
+ modulesExecutionProcessMetric = createModulesExecutionProcessMetricUseCase.execute(buildInfo)
+ }
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/create/CreateModulesExecutionProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/create/CreateModulesExecutionProcessMetricUseCase.kt
new file mode 100644
index 00000000..3fc8fede
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/create/CreateModulesExecutionProcessMetricUseCase.kt
@@ -0,0 +1,69 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesexecutionprocess.create
+
+import io.github.janbarari.gradle.analytics.domain.model.BuildInfo
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModuleExecutionProcess
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesExecutionProcessMetric
+import io.github.janbarari.gradle.core.UseCase
+import io.github.janbarari.gradle.extension.toPercentageOf
+import io.github.janbarari.gradle.extension.whenEach
+
+class CreateModulesExecutionProcessMetricUseCase(
+ private val modules: List
+): UseCase() {
+
+ override suspend fun execute(input: BuildInfo): ModulesExecutionProcessMetric {
+ val moduleExecutionProcesses = mutableListOf()
+
+ modules.whenEach {
+ val tasks = input.executedTasks.filter { it.path.startsWith(path) }
+
+ val moduleParallelExecInMillis = tasks.sumOf { it.getDurationInMillis() }
+
+ val moduleNonParallelExecInMillis = input.calculateNonParallelExecutionInMillis(tasks)
+
+ val moduleParallelRate = (moduleParallelExecInMillis - moduleNonParallelExecInMillis)
+ .toPercentageOf(moduleNonParallelExecInMillis)
+
+ val overallDuration = input.getExecutionDuration().toMillis()
+ val moduleCoverageRate = moduleNonParallelExecInMillis.toPercentageOf(overallDuration)
+
+ moduleExecutionProcesses.add(
+ ModuleExecutionProcess(
+ path = path,
+ medianExecInMillis = moduleNonParallelExecInMillis,
+ medianParallelExecInMillis = moduleParallelExecInMillis,
+ parallelRate = moduleParallelRate,
+ coverageRate = moduleCoverageRate
+ )
+ )
+ }
+
+ return ModulesExecutionProcessMetric(
+ modules = moduleExecutionProcesses
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/report/CreateModulesExecutionProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/report/CreateModulesExecutionProcessReportStage.kt
new file mode 100644
index 00000000..2c429aa4
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/report/CreateModulesExecutionProcessReportStage.kt
@@ -0,0 +1,116 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesexecutionprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.TimespanPoint
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ModuleExecutionProcess
+import io.github.janbarari.gradle.analytics.domain.model.report.ModulesExecutionProcessReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.diffPercentageOf
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.round
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.MathUtils
+
+class CreateModulesExecutionProcessReportStage(
+ private val modules: List,
+ private val metrics: List
+) : Stage {
+
+ override suspend fun process(input: Report): Report {
+ val temp = modules.map { module ->
+ var firstAvgMedianDuration: Long? = null
+ var lastAvgMedianDuration: Long? = null
+ var diffRate: Float? = null
+
+ val avgMedianExecTimespanPoints = mutableListOf()
+ val avgMedianExecs = mutableListOf()
+ val avgMedianParallelExecs = mutableListOf()
+ val avgMedianParallelRates = mutableListOf()
+ val avgMedianCoverageRates = mutableListOf()
+
+ metrics.firstOrNull { metric ->
+ metric.modulesExecutionProcessMetric.isNotNull()
+ }.whenNotNull {
+ modulesExecutionProcessMetric!!
+ .modules
+ .find { it.path == module.path }
+ .whenNotNull {
+ firstAvgMedianDuration = medianExecInMillis
+ }
+ }
+
+ metrics.lastOrNull { metric ->
+ metric.modulesExecutionProcessMetric.isNotNull()
+ }.whenNotNull {
+ modulesExecutionProcessMetric!!
+ .modules
+ .find { it.path == module.path }
+ .whenNotNull {
+ lastAvgMedianDuration = medianExecInMillis
+ }
+ }
+
+ if (firstAvgMedianDuration.isNotNull() && lastAvgMedianDuration.isNotNull())
+ diffRate = firstAvgMedianDuration!!.diffPercentageOf(lastAvgMedianDuration!!)
+
+ metrics.filter { metric ->
+ metric.modulesExecutionProcessMetric.isNotNull()
+ }.forEach { metric ->
+ metric.modulesExecutionProcessMetric!!
+ .modules
+ .find { it.path == module.path }
+ .whenNotNull {
+ avgMedianExecTimespanPoints.add(
+ TimespanPoint(
+ value = medianExecInMillis,
+ from = metric.createdAt
+ )
+ )
+ avgMedianExecs.add(medianExecInMillis)
+ avgMedianParallelExecs.add(medianParallelExecInMillis)
+ avgMedianParallelRates.add(parallelRate)
+ avgMedianCoverageRates.add(coverageRate)
+ }
+ }
+
+ ModuleExecutionProcess(
+ path = module.path,
+ avgMedianExecInMillis = MathUtils.longMedian(avgMedianExecs),
+ avgMedianParallelExecInMillis = MathUtils.longMedian(avgMedianParallelExecs),
+ avgMedianParallelRate = MathUtils.floatMedian(avgMedianParallelRates).round(),
+ avgMedianCoverageRate = MathUtils.floatMedian(avgMedianCoverageRates).round(),
+ avgMedianExecs = avgMedianExecTimespanPoints,
+ diffRate = diffRate
+ )
+ }
+
+ return input.apply {
+ modulesExecutionProcessReport = ModulesExecutionProcessReport(modules = temp)
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/report/RenderModulesExecutionProcessReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/report/RenderModulesExecutionProcessReportStage.kt
new file mode 100644
index 00000000..18bf6bd6
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/report/RenderModulesExecutionProcessReportStage.kt
@@ -0,0 +1,133 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesexecutionprocess.report
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isBiggerThanZero
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.isZero
+import io.github.janbarari.gradle.extension.mapToChartPoints
+import io.github.janbarari.gradle.extension.millisToSeconds
+import io.github.janbarari.gradle.extension.minimize
+import io.github.janbarari.gradle.extension.toArrayString
+import io.github.janbarari.gradle.extension.toIntList
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+import io.github.janbarari.gradle.utils.MathUtils
+
+/**
+ * Generates html render for [io.github.janbarari.gradle.analytics.domain.model.report.ModulesExecutionProcessReport].
+ */
+class RenderModulesExecutionProcessReportStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val CHART_MAX_COLUMNS = 12
+ private const val CHART_SUGGESTED_MIN_MAX_PERCENTAGE = 30
+ private const val MODULES_EXECUTION_PROCESS_METRIC_TEMPLATE_ID = "%modules-execution-process-metric%"
+ private const val MODULES_EXECUTION_PROCESS_METRIC_FILE_NAME = "modules-execution-process-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.modulesExecutionProcessReport.isNull()) {
+ return input.replace(MODULES_EXECUTION_PROCESS_METRIC_TEMPLATE_ID, getEmptyRender())
+ }
+
+ return input.replace(MODULES_EXECUTION_PROCESS_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getMetricRender(): String {
+ var renderedTemplate = HtmlUtils.getTemplate(MODULES_EXECUTION_PROCESS_METRIC_FILE_NAME)
+ report.modulesExecutionProcessReport.whenNotNull {
+ val min = (modules.minOfOrNull { it.avgMedianExecInMillis } ?: 0L).millisToSeconds()
+ val max = (modules.maxOfOrNull { it.avgMedianExecInMillis } ?: 0L).millisToSeconds()
+
+ val chartSuggestedMinValue = MathUtils.deductWithPercentage(min, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+ val chartSuggestedMaxValue = MathUtils.sumWithPercentage(max, CHART_SUGGESTED_MIN_MAX_PERCENTAGE)
+
+ val chartLabels: String = modules.firstOrNull()
+ ?.avgMedianExecs
+ ?.minimize(CHART_MAX_COLUMNS)
+ ?.mapToChartPoints()
+ ?.map { it.description }
+ ?.toArrayString()
+ ?: "[]"
+
+ val chartDatasets = buildString {
+ modules.whenEach {
+ append("{")
+ append("label: \"$path\",")
+ append("fill: false,")
+ append("borderColor: getColor(),")
+ append("backgroundColor: shadeColor(getColor(), 25),")
+ append("pointRadius: 0,")
+ append("data: ${avgMedianExecs.map { it.value.millisToSeconds() }.toIntList()},")
+ append("cubicInterpolationMode: 'monotone',")
+ append("tension: 0.4,")
+ append("hidden: false")
+ append("}")
+ append(",")
+ }
+ }
+
+ val tableData = buildString {
+ modules.forEachIndexed { i, module ->
+ append("")
+ append("${i+1} | ")
+ append("${module.path} | ")
+ append("${module.avgMedianExecInMillis.millisToSeconds()}s | ")
+ append("${module.avgMedianParallelExecInMillis.millisToSeconds()}s | ")
+ append("${module.avgMedianParallelRate}% | ")
+ append("${module.avgMedianCoverageRate}% | ")
+
+ if (module.diffRate.isNull())
+ append("Unknown | ")
+ else if (module.diffRate!!.isZero())
+ append("Equals | ")
+ else if (module.diffRate.isBiggerThanZero())
+ append("+${module.diffRate}% | ")
+ else
+ append("-${module.diffRate}% | ")
+
+ append("
")
+ }
+ }
+
+ renderedTemplate = renderedTemplate
+ .replace("%suggested-min-value%", chartSuggestedMinValue.toString())
+ .replace("%suggested-max-value%", chartSuggestedMaxValue.toString())
+ .replace("%chart-labels%", chartLabels)
+ .replace("%chart-datasets%", chartDatasets)
+ .replace("%table-data%", tableData)
+ }
+ return renderedTemplate
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Modules Execution Process is not available!")
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/update/UpdateModulesExecutionProcessMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/update/UpdateModulesExecutionProcessMetricStage.kt
new file mode 100644
index 00000000..96b0da3a
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/update/UpdateModulesExecutionProcessMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesexecutionprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateModulesExecutionProcessMetricStage(
+ private val updateModulesExecutionProcessMetricUseCase: UpdateModulesExecutionProcessMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesExecutionProcessMetric = updateModulesExecutionProcessMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/update/UpdateModulesExecutionProcessMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/update/UpdateModulesExecutionProcessMetricUseCase.kt
new file mode 100644
index 00000000..323017dd
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesexecutionprocess/update/UpdateModulesExecutionProcessMetricUseCase.kt
@@ -0,0 +1,76 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesexecutionprocess.update
+
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModuleExecutionProcess
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesExecutionProcessMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.MathUtils
+
+class UpdateModulesExecutionProcessMetricUseCase(
+ private val repo: DatabaseRepository,
+ private val modules: List
+): UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesExecutionProcessMetric {
+ val modulesMedianExecutionProcess = modules.map {
+ calculateMedianModuleExecutionProcess(modulePath = it.path, metrics = repo.getTemporaryMetrics())
+ }
+
+ return ModulesExecutionProcessMetric(
+ modules = modulesMedianExecutionProcess
+ )
+ }
+
+ private fun calculateMedianModuleExecutionProcess(modulePath: String, metrics: List): ModuleExecutionProcess {
+ val medianExecs = mutableListOf()
+ val medianParallelExecs = mutableListOf()
+ val medianParallelRates = mutableListOf()
+ val medianCoverageRates = mutableListOf()
+
+ metrics.whenEach {
+ modulesExecutionProcessMetric.whenNotNull {
+ modules.find { it.path == modulePath }.whenNotNull {
+ medianExecs.add(medianExecInMillis)
+ medianParallelExecs.add(medianParallelExecInMillis)
+ medianParallelRates.add(parallelRate)
+ medianCoverageRates.add(coverageRate)
+ }
+ }
+ }
+
+ return ModuleExecutionProcess(
+ path = modulePath,
+ medianExecInMillis = MathUtils.longMedian(medianExecs),
+ medianParallelExecInMillis = MathUtils.longMedian(medianParallelExecs),
+ parallelRate = MathUtils.floatMedian(medianParallelRates),
+ coverageRate = MathUtils.floatMedian(medianCoverageRates)
+ )
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/create/CreateModulesMethodCountMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/create/CreateModulesMethodCountMetricStage.kt
new file mode 100644
index 00000000..374e8e20
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/create/CreateModulesMethodCountMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesmethodcount.create
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateModulesMethodCountMetricStage(
+ private val createModulesMethodCountMetricUseCase: CreateModulesMethodCountMetricUseCase
+) : Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesMethodCountMetric = createModulesMethodCountMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/create/CreateModulesMethodCountMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/create/CreateModulesMethodCountMetricUseCase.kt
new file mode 100644
index 00000000..c04ede2a
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/create/CreateModulesMethodCountMetricUseCase.kt
@@ -0,0 +1,93 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesmethodcount.create
+
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModuleMethodCount
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesMethodCountMetric
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.isJavaFile
+import io.github.janbarari.gradle.extension.isKotlinFile
+import io.github.janbarari.gradle.extension.readText
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.utils.FileUtils
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.withContext
+import java.util.*
+
+class CreateModulesMethodCountMetricUseCase(
+ private val modules: List
+) : UseCaseNoInput() {
+
+ private val commentRegex = """(//.*)|(\/\*[^/*]*(?:(?!\/\*|\*\/)[/*][^/*]*)*\*\/)""".toRegex()
+
+ private val javaModifiers = "public|private|protected|static|final|native|synchronized|abstract|transient|"
+ private val javaMethodRegex = """($javaModifiers)+[\w\<\>\[\]\,\s]*\s*(\w+) *\([^\)]*\) *(\{|[^;])""".toRegex()
+
+ private val kotlinMethodRegex = """((fun)+[\\${'$'}\w\<\>\w\s\[\]]*\s+\w.*\([^\)]*\) *(.*) *(\{|\=))""".toRegex()
+ private val kotlinConstructorRegex =
+ """(.*class[\\${'$'}\w\<\>\w\s\[\]]*\s+\w.*\([^\)]*\)|.*constructor.*\([^\)]*\))|((\sinit) *(\{|\=))""".toRegex()
+
+ override suspend fun execute(): ModulesMethodCountMetric {
+ val modulesProperties = Collections.synchronizedList(mutableListOf())
+ withContext(dispatcher) {
+ val defers = mutableListOf>()
+ modules.whenEach {
+ defers.add(async {
+ modulesProperties.add(
+ ModuleMethodCount(
+ path = path,
+ value = getModuleMethodCount(absoluteDir)
+ )
+ )
+ })
+ }
+ defers.awaitAll()
+ }
+ return ModulesMethodCountMetric(modules = modulesProperties)
+ }
+
+ private fun getModuleMethodCount(directory: String): Int {
+ val sourcePaths = FileUtils.getModuleSources(directory)
+ var result = 0
+
+ sourcePaths.whenEach {
+ if (isKotlinFile()) {
+ val content = readText()
+ val removedComments = content.replace(commentRegex, "")
+ result += kotlinMethodRegex.findAll(removedComments).count()
+ result += kotlinConstructorRegex.findAll(removedComments).count()
+ }
+ if (isJavaFile()) {
+ val content = readText()
+ val removedComments = content.replace(commentRegex, "")
+ result += javaMethodRegex.findAll(removedComments).count()
+ }
+ }
+
+ return result
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/report/CreateModulesMethodCountReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/report/CreateModulesMethodCountReportStage.kt
new file mode 100644
index 00000000..266488bb
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/report/CreateModulesMethodCountReportStage.kt
@@ -0,0 +1,115 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesmethodcount.report
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ModuleMethodCount
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesMethodCountMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ModulesMethodCountReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.diffPercentageOf
+import io.github.janbarari.gradle.extension.hasMultipleItems
+import io.github.janbarari.gradle.extension.hasSingleItem
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.toPercentageOf
+import io.github.janbarari.gradle.extension.whenEach
+
+class CreateModulesMethodCountReportStage(
+ private val metrics: List
+) : Stage {
+
+ override suspend fun process(input: Report): Report {
+ val metrics = metrics.filter {
+ it.modulesMethodCountMetric.isNotNull()
+ }.map {
+ it.modulesMethodCountMetric!!
+ }
+
+ if (metrics.hasSingleItem()) {
+ return input.apply {
+ modulesMethodCountReport = generateSingleItemReport(metrics.single())
+ }
+ }
+
+ if (metrics.hasMultipleItems()) {
+ return input.apply {
+ modulesMethodCountReport = generateMultipleItemsReport(metrics)
+ }
+ }
+
+ return input
+ }
+
+ fun generateSingleItemReport(metric: ModulesMethodCountMetric): ModulesMethodCountReport {
+ val values = mutableListOf()
+
+ val totalSourceCount = metric.modules.sumOf { it.value }
+
+ metric.modules.whenEach {
+ values.add(
+ ModuleMethodCount(
+ path = path,
+ value = value,
+ coverageRate = value.toPercentageOf(totalSourceCount),
+ diffRate = null // The ratio does not exist when there is only one item
+ )
+ )
+ }
+
+ return ModulesMethodCountReport(
+ values = values.sortedByDescending { it.value },
+ totalMethodCount = totalSourceCount,
+ totalDiffRate = null // The ratio does not exist when there is only one item
+ )
+ }
+
+ fun generateMultipleItemsReport(metrics: List): ModulesMethodCountReport {
+ val firstTotalSourceCount = metrics.first().modules.sumOf { it.value }
+ val lastTotalSourceCount = metrics.last().modules.sumOf { it.value }
+ val totalDiffRatio = firstTotalSourceCount.diffPercentageOf(lastTotalSourceCount)
+
+ val values = mutableListOf()
+ metrics.last().modules.whenEach {
+ values.add(
+ ModuleMethodCount(
+ path = path,
+ value = value,
+ coverageRate = value.toPercentageOf(lastTotalSourceCount),
+ diffRate = calculateModuleDiffRatio(metrics, path, value)
+ )
+ )
+ }
+
+ return ModulesMethodCountReport(
+ values = values.sortedByDescending { it.value },
+ totalMethodCount = lastTotalSourceCount,
+ totalDiffRate = totalDiffRatio
+ )
+ }
+
+ fun calculateModuleDiffRatio(metrics: List, path: String, value: Int): Float? {
+ return metrics.first().modules.find { it.path == path }?.value?.diffPercentageOf(value)
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/report/RenderModulesMethodCountStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/report/RenderModulesMethodCountStage.kt
new file mode 100644
index 00000000..ff6098ad
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/report/RenderModulesMethodCountStage.kt
@@ -0,0 +1,107 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesmethodcount.report
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+
+class RenderModulesMethodCountStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val MODULES_METHOD_COUNT_METRIC_TEMPLATE_ID = "%modules-method-count-metric%"
+ private const val MODULES_METHOD_COUNT_METRIC_TEMPLATE_FILE_NAME = "modules-method-count-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.modulesMethodCountReport.isNull())
+ return input.replace(MODULES_METHOD_COUNT_METRIC_TEMPLATE_ID, getEmptyRender())
+
+ return input.replace(MODULES_METHOD_COUNT_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Modules Method Count is not available!")
+ }
+
+ fun getMetricRender(): String {
+ val totalMethodCount = report.modulesMethodCountReport?.totalMethodCount ?: 0
+
+ var totalDiffRatioRender = "- | "
+ report.modulesMethodCountReport.whenNotNull {
+ totalDiffRate.whenNotNull {
+ totalDiffRatioRender = if (this > 0) {
+ "+${this}% | "
+ } else if (this < 0) {
+ "-${this}% | "
+ } else {
+ "Equals | "
+ }
+ }
+ }
+
+ val tableData = buildString {
+ report.modulesMethodCountReport?.values?.forEachIndexed { index, it ->
+ var diffRatioRender = "- | "
+ it.diffRate.whenNotNull {
+ diffRatioRender = if (this > 0) {
+ "+${this}% | "
+ } else if (this < 0) {
+ "-${this}% | "
+ } else {
+ "Equals | "
+ }
+ }
+ append(
+ """
+
+ ${index + 1} |
+ ${it.path} |
+ ${it.value} |
+ ${it.coverageRate}% |
+ $diffRatioRender
+
+ """.trimIndent()
+ )
+ }
+ }
+
+ val moduleLabels = report.modulesMethodCountReport?.values?.map { "\"${it.path}\"" }
+ val moduleValues = report.modulesMethodCountReport?.values?.map { it.value }
+
+ var renderedTemplate = HtmlUtils.getTemplate(MODULES_METHOD_COUNT_METRIC_TEMPLATE_FILE_NAME)
+ renderedTemplate = renderedTemplate
+ .replace("%table-data%", tableData)
+ .replace("%total-method-count%", totalMethodCount.toString())
+ .replace("%total-diff-rate%", totalDiffRatioRender)
+ .replace("%module-labels%", moduleLabels.toString())
+ .replace("%module-values%", moduleValues.toString())
+
+ return renderedTemplate
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/update/UpdateModulesMethodCountMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/update/UpdateModulesMethodCountMetricStage.kt
new file mode 100644
index 00000000..5654f929
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/update/UpdateModulesMethodCountMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesmethodcount.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateModulesMethodCountMetricStage(
+ private val updateModulesMethodCountMetricUseCase: UpdateModulesMethodCountMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesMethodCountMetric = updateModulesMethodCountMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/update/UpdateModulesMethodCountMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/update/UpdateModulesMethodCountMetricUseCase.kt
new file mode 100644
index 00000000..7bbbfa2e
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesmethodcount/update/UpdateModulesMethodCountMetricUseCase.kt
@@ -0,0 +1,37 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesmethodcount.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesMethodCountMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+
+class UpdateModulesMethodCountMetricUseCase(
+ private val repo: DatabaseRepository
+) : UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesMethodCountMetric {
+ return repo.getTemporaryMetrics().last().modulesMethodCountMetric!!
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/create/CreateModulesSourceCountMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/create/CreateModulesSourceCountMetricStage.kt
new file mode 100644
index 00000000..a5e62d74
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/create/CreateModulesSourceCountMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesourcecount.create
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateModulesSourceCountMetricStage(
+ private val createModulesSourceCountMetricUseCase: CreateModulesSourceCountMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesSourceCountMetric = createModulesSourceCountMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/create/CreateModulesSourceCountMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/create/CreateModulesSourceCountMetricUseCase.kt
new file mode 100644
index 00000000..684f28b7
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/create/CreateModulesSourceCountMetricUseCase.kt
@@ -0,0 +1,60 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesourcecount.create
+
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModuleSourceCount
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesSourceCountMetric
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.utils.FileUtils
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.withContext
+import java.util.*
+
+class CreateModulesSourceCountMetricUseCase(
+ private val modules: List
+) : UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesSourceCountMetric {
+ val result = Collections.synchronizedList(mutableListOf())
+ withContext(dispatcher) {
+ val defers = mutableListOf>()
+ modules.whenEach {
+ defers.add(async {
+ result.add(
+ ModuleSourceCount(
+ path = path,
+ value = FileUtils.getModuleSources(absoluteDir).size
+ )
+ )
+ })
+ }
+ defers.awaitAll()
+ }
+ return ModulesSourceCountMetric(modules = result)
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/report/CreateModulesSourceCountReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/report/CreateModulesSourceCountReportStage.kt
new file mode 100644
index 00000000..060153b7
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/report/CreateModulesSourceCountReportStage.kt
@@ -0,0 +1,114 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesourcecount.report
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ModuleSourceCount
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesSourceCountMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ModulesSourceCountReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.hasMultipleItems
+import io.github.janbarari.gradle.extension.hasSingleItem
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.diffPercentageOf
+import io.github.janbarari.gradle.extension.toPercentageOf
+import io.github.janbarari.gradle.extension.whenEach
+
+class CreateModulesSourceCountReportStage(
+ private val metrics: List
+) : Stage {
+
+ override suspend fun process(input: Report): Report {
+ val metrics = metrics.filter {
+ it.modulesSourceCountMetric.isNotNull()
+ }.map {
+ it.modulesSourceCountMetric!!
+ }
+
+ if (metrics.hasSingleItem()) {
+ return input.apply {
+ modulesSourceCountReport = generateSingleItemReport(metrics.single())
+ }
+ }
+
+ if (metrics.hasMultipleItems()) {
+ return input.apply {
+ modulesSourceCountReport = generateMultipleItemsReport(metrics)
+ }
+ }
+
+ return input
+ }
+
+ fun generateSingleItemReport(metric: ModulesSourceCountMetric): ModulesSourceCountReport {
+ val values = mutableListOf()
+ val totalSourceCount = metric.modules.sumOf { it.value }
+
+ metric.modules.whenEach {
+ values.add(
+ ModuleSourceCount(
+ path = path,
+ value = value,
+ coverageRate = value.toPercentageOf(totalSourceCount),
+ diffRate = null // The ratio does not exist when there is only one item
+ )
+ )
+ }
+
+ return ModulesSourceCountReport(
+ values = values.sortedByDescending { it.value },
+ totalSourceCount = totalSourceCount,
+ totalDiffRate = null // The ratio does not exist when there is only one item
+ )
+ }
+
+ fun generateMultipleItemsReport(metrics: List): ModulesSourceCountReport {
+ val firstTotalSourceCount = metrics.first().modules.sumOf { it.value }
+ val lastTotalSourceCount = metrics.last().modules.sumOf { it.value }
+ val totalDiffRatio = firstTotalSourceCount.diffPercentageOf(lastTotalSourceCount)
+
+ val values = mutableListOf()
+ metrics.last().modules.whenEach {
+ values.add(
+ ModuleSourceCount(
+ path = path,
+ value = value,
+ coverageRate = value.toPercentageOf(lastTotalSourceCount),
+ diffRate = calculateModuleDiffRatio(metrics, path, value)
+ )
+ )
+ }
+
+ return ModulesSourceCountReport(
+ values = values.sortedByDescending { it.value },
+ totalSourceCount = lastTotalSourceCount,
+ totalDiffRate = totalDiffRatio
+ )
+ }
+
+ fun calculateModuleDiffRatio(metrics: List, path: String, value: Int): Float? {
+ return metrics.first().modules.find { it.path == path }?.value?.diffPercentageOf(value)
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/report/RenderModulesSourceCountStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/report/RenderModulesSourceCountStage.kt
new file mode 100644
index 00000000..582a6c76
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/report/RenderModulesSourceCountStage.kt
@@ -0,0 +1,107 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesourcecount.report
+
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.isNull
+import io.github.janbarari.gradle.extension.whenNotNull
+import io.github.janbarari.gradle.utils.HtmlUtils
+
+class RenderModulesSourceCountStage(
+ private val report: Report
+) : Stage {
+
+ companion object {
+ private const val MODULES_SOURCE_COUNT_METRIC_TEMPLATE_ID = "%modules-source-count-metric%"
+ private const val MODULES_SOURCE_COUNT_METRIC_TEMPLATE_FILE_NAME = "modules-source-count-metric-template"
+ }
+
+ override suspend fun process(input: String): String {
+ if (report.modulesSourceCountReport.isNull())
+ return input.replace(MODULES_SOURCE_COUNT_METRIC_TEMPLATE_ID, getEmptyRender())
+
+ return input.replace(MODULES_SOURCE_COUNT_METRIC_TEMPLATE_ID, getMetricRender())
+ }
+
+ fun getEmptyRender(): String {
+ return HtmlUtils.renderMessage("Modules Source Count is not available!")
+ }
+
+ fun getMetricRender(): String {
+ val totalSourceCount = report.modulesSourceCountReport?.totalSourceCount ?: 0
+
+ var totalDiffRatioRender = "- | "
+ report.modulesSourceCountReport.whenNotNull {
+ totalDiffRate.whenNotNull {
+ totalDiffRatioRender = if (this > 0) {
+ "+${this}% | "
+ } else if (this < 0) {
+ "-${this}% | "
+ } else {
+ "Equals | "
+ }
+ }
+ }
+
+ val tableData = buildString {
+ report.modulesSourceCountReport?.values?.forEachIndexed { index, it ->
+ var diffRatioRender = "- | "
+ it.diffRate.whenNotNull {
+ diffRatioRender = if (this > 0) {
+ "+${this}% | "
+ } else if (this < 0){
+ "-${this}% | "
+ } else {
+ "Equals | "
+ }
+ }
+ append(
+ """
+
+ ${index + 1} |
+ ${it.path} |
+ ${it.value} |
+ ${it.coverageRate}% |
+ $diffRatioRender
+
+ """.trimIndent()
+ )
+ }
+ }
+
+ val moduleLabels = report.modulesSourceCountReport?.values?.map { "\"${it.path}\"" }
+ val moduleValues = report.modulesSourceCountReport?.values?.map { it.value }
+
+ var renderedTemplate = HtmlUtils.getTemplate(MODULES_SOURCE_COUNT_METRIC_TEMPLATE_FILE_NAME)
+ renderedTemplate = renderedTemplate
+ .replace("%table-data%", tableData)
+ .replace("%total-source-count%", totalSourceCount.toString())
+ .replace("%total-diff-rate%", totalDiffRatioRender)
+ .replace("%module-labels%", moduleLabels.toString())
+ .replace("%module-values%", moduleValues.toString())
+
+ return renderedTemplate
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/update/UpdateModulesSourceCountMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/update/UpdateModulesSourceCountMetricStage.kt
new file mode 100644
index 00000000..b283b157
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/update/UpdateModulesSourceCountMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesourcecount.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class UpdateModulesSourceCountMetricStage(
+ private val updateModulesSourceCountMetricUseCase: UpdateModulesSourceCountMetricUseCase
+): Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesSourceCountMetric = updateModulesSourceCountMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/update/UpdateModulesSourceCountMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/update/UpdateModulesSourceCountMetricUseCase.kt
new file mode 100644
index 00000000..6a9a89d9
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulesourcecount/update/UpdateModulesSourceCountMetricUseCase.kt
@@ -0,0 +1,37 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulesourcecount.update
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesSourceCountMetric
+import io.github.janbarari.gradle.analytics.domain.repository.DatabaseRepository
+import io.github.janbarari.gradle.core.UseCaseNoInput
+
+class UpdateModulesSourceCountMetricUseCase(
+ private val repo: DatabaseRepository
+) : UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesSourceCountMetric {
+ return repo.getTemporaryMetrics().last().modulesSourceCountMetric!!
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulessourcesize/create/CreateModulesSourceSizeMetricStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulessourcesize/create/CreateModulesSourceSizeMetricStage.kt
new file mode 100644
index 00000000..b89b4d27
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulessourcesize/create/CreateModulesSourceSizeMetricStage.kt
@@ -0,0 +1,38 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulessourcesize.create
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.core.Stage
+
+class CreateModulesSourceSizeMetricStage(
+ private val createModulesSourceSizeMetricUseCase: CreateModulesSourceSizeMetricUseCase
+) : Stage {
+
+ override suspend fun process(input: BuildMetric): BuildMetric {
+ return input.apply {
+ modulesSourceSizeMetric = createModulesSourceSizeMetricUseCase.execute()
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulessourcesize/create/CreateModulesSourceSizeMetricUseCase.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulessourcesize/create/CreateModulesSourceSizeMetricUseCase.kt
new file mode 100644
index 00000000..d57c22f0
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulessourcesize/create/CreateModulesSourceSizeMetricUseCase.kt
@@ -0,0 +1,65 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulessourcesize.create
+
+import io.github.janbarari.gradle.analytics.domain.model.Module
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesSourceSizeMetric
+import io.github.janbarari.gradle.core.UseCaseNoInput
+import io.github.janbarari.gradle.extension.whenEach
+import io.github.janbarari.gradle.utils.FileUtils
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.withContext
+import java.util.*
+
+class CreateModulesSourceSizeMetricUseCase(
+ private val modules: List
+) : UseCaseNoInput() {
+
+ override suspend fun execute(): ModulesSourceSizeMetric {
+ val modulesProperties = Collections.synchronizedList(mutableListOf())
+ withContext(dispatcher) {
+ val defers = mutableListOf>()
+ modules.whenEach {
+ defers.add(async {
+ modulesProperties.add(
+ ModulesSourceSizeMetric.ModuleSourceSize(
+ path = path,
+ sizeInKb = getModuleSourceSizeInKb(absoluteDir)
+ )
+ )
+ })
+ }
+ defers.awaitAll()
+ }
+ return ModulesSourceSizeMetric(modules = modulesProperties)
+ }
+
+ private fun getModuleSourceSizeInKb(directory: String): Long {
+ return FileUtils
+ .getModuleSources(directory)
+ .sumOf { it.toFile().length() / 1024L }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulessourcesize/report/CreateModulesSourceSizeReportStage.kt b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulessourcesize/report/CreateModulesSourceSizeReportStage.kt
new file mode 100644
index 00000000..e3a392ba
--- /dev/null
+++ b/src/main/kotlin/io/github/janbarari/gradle/analytics/metric/modulessourcesize/report/CreateModulesSourceSizeReportStage.kt
@@ -0,0 +1,114 @@
+/**
+ * MIT License
+ * Copyright (c) 2022 Mehdi Janbarari (@janbarari)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.github.janbarari.gradle.analytics.metric.modulessourcesize.report
+
+import io.github.janbarari.gradle.analytics.domain.model.metric.BuildMetric
+import io.github.janbarari.gradle.analytics.domain.model.metric.ModulesSourceSizeMetric
+import io.github.janbarari.gradle.analytics.domain.model.report.ModulesSourceSizeReport
+import io.github.janbarari.gradle.analytics.domain.model.report.Report
+import io.github.janbarari.gradle.core.Stage
+import io.github.janbarari.gradle.extension.diffPercentageOf
+import io.github.janbarari.gradle.extension.hasMultipleItems
+import io.github.janbarari.gradle.extension.hasSingleItem
+import io.github.janbarari.gradle.extension.isNotNull
+import io.github.janbarari.gradle.extension.toPercentageOf
+import io.github.janbarari.gradle.extension.whenEach
+
+class CreateModulesSourceSizeReportStage(
+ private val metrics: List
+) : Stage {
+
+ override suspend fun process(input: Report): Report {
+ val metrics = metrics.filter {
+ it.modulesSourceSizeMetric.isNotNull()
+ }.map {
+ it.modulesSourceSizeMetric!!
+ }
+
+ if (metrics.hasSingleItem()) {
+ return input.apply {
+ modulesSourceSizeReport = generateSingleItemReport(metrics.single())
+ }
+ }
+
+ if (metrics.hasMultipleItems()) {
+ return input.apply {
+ modulesSourceSizeReport = generateMultipleItemsReport(metrics)
+ }
+ }
+
+ return input
+ }
+
+ fun generateSingleItemReport(metric: ModulesSourceSizeMetric): ModulesSourceSizeReport {
+ val values = mutableListOf