diff --git a/.editorconfig b/.editorconfig
index ab8d30e..5c23ee0 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,11 +1,14 @@
root = true
[*.{kt,kts}]
-disabled_rules = filename
-max_line_length = off
insert_final_newline = true
ij_kotlin_name_count_to_use_star_import = 999
ij_kotlin_name_count_to_use_star_import_for_members = 999
ij_java_class_count_to_use_import_on_demand = 999
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true
+
+ktlint_ignore_back_ticked_identifier = true
+
+# Disabled annotation formatting so @Inject constructor() doesn't go to new line
+ktlint_standard_annotation = disabled
diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml
index c0df3ef..d09e5d5 100644
--- a/.github/workflows/commit.yml
+++ b/.github/workflows/commit.yml
@@ -1,155 +1,19 @@
name: Commit
-on: push
-
-env:
- api_level: 29
- commitlint_version: '17'
- conventional_changelog_version: '5'
- java_version: 11
- ktlint_version: '0.46.1'
- node_version: 18
- semantic_release_version: '20'
+on: [ push, workflow_dispatch ]
jobs:
- commit_lint:
- name: Commit Lint
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v3.3.0
- with:
- fetch-depth: 0
- - name: Run Commit Lint
- id: commitlint
- uses: ./.github/actions/commit-lint
- with:
- node_version: ${{ env.node_version }}
- commitlint_version: ${{ env.commitlint_version }}
-
- code_lint:
- name: Code Lint
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v3.3.0
- - name: Run ktlint
- id: ktlint
- uses: ./.github/actions/code-lint
- with:
- ktlint_version: ${{ env.ktlint_version }}
-
- validation:
- name: "Validation"
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: gradle/actions/wrapper-validation@v3
-
- determine_version:
- name: Version Determination
- runs-on: ubuntu-latest
- outputs:
- releaseType: ${{ steps.determine_version.outputs.releaseType }}
- releaseChannel: ${{ steps.determine_version.outputs.releaseChannel }}
- buildVersion: ${{ steps.determine_version.outputs.buildVersion }}
- steps:
- - name: Checkout
- uses: actions/checkout@v3.3.0
- - name: Determine Version
- id: determine_version
- uses: ./.github/actions/determine-version
- with:
- node_version: ${{ env.node_version }}
- semantic_release_version: ${{ env.semantic_release_version }}
- conventional_changelog_version: ${{ env.conventional_changelog_version }}
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- build:
- name: Build
- needs: [ commit_lint, code_lint, validation ]
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v3.3.0
- - name: Build
- id: build
- uses: ./.github/actions/build
- with:
- java_version: ${{ env.java_version }}
- env:
- BUILD_VERSION: "${{ needs.determine_version.outputs.buildVersion }}"
-
- unit_tests:
- name: Unit Tests
- needs: [ commit_lint, code_lint, validation ]
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v3.3.0
- - name: Unit Tests
- id: unit_tests
- uses: ./.github/actions/unit-tests
- with:
- java_version: ${{ env.java_version }}
-
- instrumentation_tests:
- name: Instrumentation Tests
- needs: [ commit_lint, code_lint ]
- runs-on: macos-11
- steps:
- - name: Checkout
- uses: actions/checkout@v3.3.0
- - name: Run Tests
- id: instrumentation_tests
- uses: ./.github/actions/instrumentation-test
- with:
- java_version: ${{ env.java_version }}
- api_level: ${{ env.api_level }}
-
- release:
- name: Release
- runs-on: ubuntu-latest
- needs: [ determine_version, build, unit_tests, instrumentation_tests ]
- if: needs.determine_version.outputs.releaseType != ''
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- outputs:
- releaseType: ${{ steps.release.outputs.releaseType }}
- releaseChannel: ${{ steps.release.outputs.releaseChannel }}
- buildVersion: ${{ steps.release.outputs.buildVersion }}
- steps:
- - name: Checkout
- uses: actions/checkout@v3.3.0
- - name: Release
- id: release
- uses: ./.github/actions/release
- with:
- node_version: ${{ env.node_version }}
- semantic_release_version: ${{ env.semantic_release_version }}
- conventional_changelog_version: ${{ env.conventional_changelog_version }}
-
- publish:
- name: Publication
- runs-on: ubuntu-latest
- needs: release
- if: needs.release.outputs.releaseType != ''
- env:
- RELEASE_TYPE: ${{ needs.release.outputs.releaseType }}
- RELEASE_CHANNEL: ${{ needs.release.outputs.releaseChannel }}
- BUILD_VERSION: ${{ needs.release.outputs.buildVersion }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ semantic_library_workflow:
+ name: push
+ uses: krogerco/Shared-CI-Workflow-Android/.github/workflows/semantic_library_workflow.yml@v1.5.0
+ with:
+ java_version: '24'
+ ktlint_version: '-1'
+ test_command: 'test'
+ secrets:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralUsername }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralPassword }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKey }}
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyId }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyPassword }}
- steps:
- - name: Checkout
- uses: actions/checkout@v3.3.0
- - name: Publish
- id: publish
- uses: ./.github/actions/publish
- with:
- java_version: ${{ env.java_version }}
\ No newline at end of file
+ REPO_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index 157f5d7..480aa77 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -10,6 +10,10 @@ jobs:
name: Check PR Title
runs-on: ubuntu-latest
steps:
- - uses: thehanimo/pr-title-checker@v1.3.4
+ - uses: thehanimo/pr-title-checker@v1.4.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ github_configuration_owner: 'krogerco'
+ github_configuration_repo: 'Shared-CI-Workflow-Android'
+ github_configuration_path: '.github/config/pr-title-checker-config.json'
+ github_configuration_ref: 'v1.0.0'
diff --git a/android/build.gradle.kts b/android/build.gradle.kts
index 52253d5..222077c 100644
--- a/android/build.gradle.kts
+++ b/android/build.gradle.kts
@@ -1,15 +1,26 @@
+import com.kroger.gradle.config.junit5
+
plugins {
- id(Plugins.androidLibrary.id)
- id(Plugins.release.id)
+ alias(libs.plugins.conventions.publishedAndroidLibrary)
+}
+
+android {
+ namespace = "com.kroger.telemetry.android"
+}
+
+kover {
+ currentProject {
+ createVariant("default") {
+ add("debug")
+ }
+ }
}
dependencies {
api(project(":telemetry"))
- implementation(libs.coroutinesAndroid)
- implementation(libs.stdLib)
+ implementation(libs.kotlinx.coroutinesAndroid)
- testImplementation(libs.coroutinesTest)
- testImplementation(libs.jupiterApi)
- testRuntimeOnly(libs.jupiterEngine)
+ junit5()
+ testImplementation(libs.kotlinx.coroutinesTest)
}
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
deleted file mode 100644
index 915c254..0000000
--- a/android/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/android/src/main/java/com/kroger/telemetry/android/facet/ToastFacet.kt b/android/src/main/java/com/kroger/telemetry/android/facet/ToastFacet.kt
index 47460e8..ee74f4f 100644
--- a/android/src/main/java/com/kroger/telemetry/android/facet/ToastFacet.kt
+++ b/android/src/main/java/com/kroger/telemetry/android/facet/ToastFacet.kt
@@ -26,4 +26,6 @@ package com.kroger.telemetry.android.facet
import com.kroger.telemetry.facet.Facet
-public data class ToastFacet(val message: String) : Facet
+public data class ToastFacet(
+ val message: String,
+) : Facet
diff --git a/android/src/main/java/com/kroger/telemetry/android/relay/LogRelay.kt b/android/src/main/java/com/kroger/telemetry/android/relay/LogRelay.kt
index 057e3ca..bd48016 100644
--- a/android/src/main/java/com/kroger/telemetry/android/relay/LogRelay.kt
+++ b/android/src/main/java/com/kroger/telemetry/android/relay/LogRelay.kt
@@ -42,11 +42,12 @@ private val logPrinter: (PrintRelay.Message) -> Unit = { message ->
Log.println(message.significance.toLogPriority(), message.tag, message.value)
}
-private fun Significance.toLogPriority(): Int = when (this) {
- Significance.VERBOSE -> Log.VERBOSE
- Significance.DEBUG -> Log.DEBUG
- Significance.INFORMATIONAL -> Log.INFO
- Significance.WARNING -> Log.WARN
- Significance.ERROR -> Log.ERROR
- Significance.INTERNAL_ERROR -> Log.ERROR
-}
+private fun Significance.toLogPriority(): Int =
+ when (this) {
+ Significance.VERBOSE -> Log.VERBOSE
+ Significance.DEBUG -> Log.DEBUG
+ Significance.INFORMATIONAL -> Log.INFO
+ Significance.WARNING -> Log.WARN
+ Significance.ERROR -> Log.ERROR
+ Significance.INTERNAL_ERROR -> Log.ERROR
+ }
diff --git a/android/src/main/java/com/kroger/telemetry/android/relay/ToastRelay.kt b/android/src/main/java/com/kroger/telemetry/android/relay/ToastRelay.kt
index 471e2a4..117e033 100644
--- a/android/src/main/java/com/kroger/telemetry/android/relay/ToastRelay.kt
+++ b/android/src/main/java/com/kroger/telemetry/android/relay/ToastRelay.kt
@@ -44,7 +44,6 @@ public class ToastRelay internal constructor(
private val toaster: Toaster,
public val configuration: Configuration,
) : Relay {
-
/**
* A set of configurable options for a ToastRelay.
* @property toastLength Should be one of [Toast.LENGTH_SHORT] or [Toast.LENGTH_LONG]. Defaults to short.
@@ -83,31 +82,42 @@ public class ToastRelay internal constructor(
override suspend fun process(event: Event) {
val toastFacets = event.facets.filterIsInstance(ToastFacet::class.java)
- val shouldToastWithoutToastFacet = event.hasHighEnoughSignificance() &&
- configuration.toastSignificantEvents
+ val shouldToastWithoutToastFacet =
+ event.hasHighEnoughSignificance() &&
+ configuration.toastSignificantEvents
val shouldToast = toastFacets.isNotEmpty() || shouldToastWithoutToastFacet
if (shouldToast && configuration.enabled) {
val message = toastFacets.firstOrNull()?.message ?: event.description
- val correctedLength = when (configuration.toastLength) {
- Toast.LENGTH_SHORT -> configuration.toastLength
- Toast.LENGTH_LONG -> configuration.toastLength
- else -> Toast.LENGTH_SHORT
- }
+ val correctedLength =
+ when (configuration.toastLength) {
+ Toast.LENGTH_SHORT -> configuration.toastLength
+ Toast.LENGTH_LONG -> configuration.toastLength
+ else -> Toast.LENGTH_SHORT
+ }
toaster.toast(message, correctedLength)
}
}
- private fun Event.hasHighEnoughSignificance(): Boolean = facets
- .filterIsInstance(Significance::class.java)
- .any { it >= configuration.minimumSignificance }
+ private fun Event.hasHighEnoughSignificance(): Boolean =
+ facets
+ .filterIsInstance(Significance::class.java)
+ .any { it >= configuration.minimumSignificance }
}
internal interface Toaster {
- suspend fun toast(message: String, length: Int)
+ suspend fun toast(
+ message: String,
+ length: Int,
+ )
}
-private class ToasterImpl(private val context: Context) : Toaster {
- override suspend fun toast(message: String, length: Int) = withContext(Dispatchers.Main) {
+private class ToasterImpl(
+ private val context: Context,
+) : Toaster {
+ override suspend fun toast(
+ message: String,
+ length: Int,
+ ) = withContext(Dispatchers.Main) {
Toast.makeText(context, message, length).show()
}
}
@@ -119,8 +129,9 @@ private interface Toggles {
private fun sampleToastConfig() {
val propertyChangeConfig = ToastRelay.Configuration.Default(toastSignificantEvents = true)
- class PropertyBehaviorChangeConfig(private val toggles: Toggles) :
- ToastRelay.Configuration by ToastRelay.Configuration.Default() {
+ class PropertyBehaviorChangeConfig(
+ private val toggles: Toggles,
+ ) : ToastRelay.Configuration by ToastRelay.Configuration.Default() {
override var enabled: Boolean
get() = toggles["ToastRelay Toggle"]
set(_) = Unit
diff --git a/android/src/test/java/com/kroger/telemetry/android/relay/ToastRelayTest.kt b/android/src/test/java/com/kroger/telemetry/android/relay/ToastRelayTest.kt
index f9012bb..f3cd683 100644
--- a/android/src/test/java/com/kroger/telemetry/android/relay/ToastRelayTest.kt
+++ b/android/src/test/java/com/kroger/telemetry/android/relay/ToastRelayTest.kt
@@ -29,7 +29,7 @@ import com.kroger.telemetry.Event
import com.kroger.telemetry.android.facet.ToastFacet
import com.kroger.telemetry.facet.Facet
import com.kroger.telemetry.facet.Significance
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
@@ -39,7 +39,11 @@ internal class ToastRelayTest {
private class FakeToaster : Toaster {
var didToast = false
var fakeFunToast: (String, Int) -> Unit = { _, _ -> didToast = true }
- override suspend fun toast(message: String, length: Int) = fakeFunToast(message, length)
+
+ override suspend fun toast(
+ message: String,
+ length: Int,
+ ) = fakeFunToast(message, length)
}
private data class TestConfig(
@@ -61,7 +65,7 @@ internal class ToastRelayTest {
@Test
fun `GIVEN toast relay disabled WHEN event received THEN nothing is toasted`() =
- runBlockingTest {
+ runTest {
val config = TestConfig().copy(enabled = false)
val relay = config.getRelay()
@@ -76,7 +80,7 @@ internal class ToastRelayTest {
@Test
fun `GIVEN toast relay WHEN event received with toast facet THEN facet is toasted`() =
- runBlockingTest {
+ runTest {
val config = TestConfig()
val relay = config.getRelay()
@@ -91,11 +95,12 @@ internal class ToastRelayTest {
@Test
fun `GIVEN toast relay configured to toast all WHEN event received no significance THEN event is not toasted`() =
- runBlockingTest {
- val config = TestConfig().copy(
- toastSignificantEvents = true,
- minimumSignificance = Significance.ERROR,
- )
+ runTest {
+ val config =
+ TestConfig().copy(
+ toastSignificantEvents = true,
+ minimumSignificance = Significance.ERROR,
+ )
val relay = config.getRelay()
relay.process(
@@ -109,11 +114,12 @@ internal class ToastRelayTest {
@Test
fun `GIVEN toast relay configured to toast all WHEN event received with lower than minimum significance THEN event is not toasted`() =
- runBlockingTest {
- val config = TestConfig().copy(
- toastSignificantEvents = true,
- minimumSignificance = Significance.ERROR,
- )
+ runTest {
+ val config =
+ TestConfig().copy(
+ toastSignificantEvents = true,
+ minimumSignificance = Significance.ERROR,
+ )
val relay = config.getRelay()
relay.process(
@@ -127,11 +133,12 @@ internal class ToastRelayTest {
@Test
fun `GIVEN toast relay configured to toast all WHEN event received with minimum significance THEN event is toasted`() =
- runBlockingTest {
- val config = TestConfig().copy(
- toastSignificantEvents = true,
- minimumSignificance = Significance.ERROR,
- )
+ runTest {
+ val config =
+ TestConfig().copy(
+ toastSignificantEvents = true,
+ minimumSignificance = Significance.ERROR,
+ )
val relay = config.getRelay()
relay.process(
@@ -145,7 +152,7 @@ internal class ToastRelayTest {
@Test
fun `GIVEN toast relay configured with bad length WHEN toasting THEN uses length short as default`() =
- runBlockingTest {
+ runTest {
val toaster = FakeToaster()
var lengthUsed = 42
toaster.fakeFunToast = { _, length -> lengthUsed = length }
@@ -163,7 +170,7 @@ internal class ToastRelayTest {
@Test
fun `GIVEN an enabled toast relay WHEN disabled THEN toasts will not be shown`() =
- runBlockingTest {
+ runTest {
val config = TestConfig().copy(enabled = true)
val relay = config.getRelay()
@@ -182,8 +189,9 @@ internal class ToastRelayTest {
fun `GIVEN config with mutable backing data WHEN backing data is changed THEN config reflects update`() {
val mutableBackingInstance = mutableListOf(false)
- class MutableConfig(private val mutableBackingProp: List) :
- ToastRelay.Configuration by ToastRelay.Configuration.Default() {
+ class MutableConfig(
+ private val mutableBackingProp: List,
+ ) : ToastRelay.Configuration by ToastRelay.Configuration.Default() {
override var enabled: Boolean
get() = mutableBackingProp.first()
set(_) = Unit
diff --git a/build.gradle.kts b/build.gradle.kts
index 5814f36..301e053 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,48 +1,32 @@
-import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask
-
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-buildscript {
- repositories {
- mavenCentral()
- google()
- }
-}
-
-allprojects {
- group = "com.kroger.telemetry"
- version = "0.0.1"
-
- repositories {
- mavenCentral()
- google()
- }
-}
-
plugins {
- id("com.github.ben-manes.versions") version "0.36.0"
- id("org.jlleitschuh.gradle.ktlint") version "11.1.0"
+ alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.android.junit5) apply false
+ alias(libs.plugins.compose) apply false
+ alias(libs.plugins.conventions.androidApplication) apply false
+ alias(libs.plugins.conventions.publishedAndroidLibrary) apply false
+ alias(libs.plugins.conventions.publishedKotlinLibrary) apply false
+ alias(libs.plugins.conventions.root)
+ alias(libs.plugins.dependencyAnalysis) apply false
+ alias(libs.plugins.dokka)
+ alias(libs.plugins.gradleVersions) apply false
+ alias(libs.plugins.dagger.hilt) apply false
+ alias(libs.plugins.kotlinter) apply false
+ alias(libs.plugins.kotlinx.kover) apply true
+ alias(libs.plugins.ksp) apply false
+ alias(libs.plugins.mavenPublish) apply false
}
-subprojects {
- apply(plugin = "org.jlleitschuh.gradle.ktlint")
-
- configure {
- version.set("0.46.1")
- android.set(true)
- debug.set(true)
- reporters {
- reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE)
- }
- filter {
- exclude("**/generated/**", "**/src/test/**")
+kover {
+ currentProject {
+ createVariant("default") {
+ // no sources and tests in root module
}
}
}
-tasks.named("dependencyUpdates", DependencyUpdatesTask::class.java).configure {
- // optional parameters
- checkForGradleUpdate = true
- outputFormatter = "json"
- outputDir = "build/dependencyUpdates"
- reportfileName = "report"
+dependencies {
+ kover(project(":android"))
+ kover(project(":context-aware"))
+ kover(project(":firebase"))
+ kover(project(":telemetry"))
}
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
deleted file mode 100644
index e6b174b..0000000
--- a/buildSrc/build.gradle.kts
+++ /dev/null
@@ -1,27 +0,0 @@
-plugins {
- `kotlin-dsl`
-}
-
-buildscript {
- repositories {
- mavenCentral()
- google()
- }
-}
-
-allprojects {
- repositories {
- mavenCentral()
- google()
- }
-}
-
-dependencies {
- implementation("com.android.tools.build:gradle:7.3.1")
- implementation("com.squareup:javapoet:1.13.0")
- implementation("de.mannodermaus.gradle.plugins:android-junit5:1.8.0.0")
- implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31")
- implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.5.31")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3")
- implementation("com.vanniktech:gradle-maven-publish-plugin:0.22.0")
-}
diff --git a/buildSrc/src/main/java/Plugins.kt b/buildSrc/src/main/java/Plugins.kt
deleted file mode 100644
index ed5c9be..0000000
--- a/buildSrc/src/main/java/Plugins.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2021 The Kroger Co. All rights reserved.
- *
- * 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.
- */
-
-object Plugins {
- /**
- * @param id used to reference the plugin inside of a `plugins` block
- * @param coordinates used to add the plugin to the classpath
- */
- data class Plugin(val id: String, val coordinates: String)
-
- val androidLibrary = Plugin("android-library-module", "N/A")
- val javaLibrary = Plugin("java-library-module", "N/A")
- val release = Plugin("release-module", "N/A")
-}
diff --git a/buildSrc/src/main/java/SdkVersions.kt b/buildSrc/src/main/java/SdkVersions.kt
deleted file mode 100644
index 9dc34bb..0000000
--- a/buildSrc/src/main/java/SdkVersions.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2021 The Kroger Co. All rights reserved.
- *
- * 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.
- */
-
-/**
- * Project-specific Version numbers
- */
-object SdkVersions {
- const val targetSdkVersion = 32
- const val compileSdkVersion = 32
- const val minSdkVersion = 24
-}
diff --git a/buildSrc/src/main/java/android-library-module.gradle.kts b/buildSrc/src/main/java/android-library-module.gradle.kts
deleted file mode 100644
index 81989cb..0000000
--- a/buildSrc/src/main/java/android-library-module.gradle.kts
+++ /dev/null
@@ -1,58 +0,0 @@
-plugins {
- id("com.android.library")
- kotlin("android")
- id("jacoco")
- id("de.mannodermaus.android-junit5")
- id("org.jetbrains.dokka")
-}
-
-android {
- compileSdk = SdkVersions.compileSdkVersion
-
- defaultConfig {
- minSdk = (SdkVersions.minSdkVersion)
- targetSdk = (SdkVersions.targetSdkVersion)
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
- }
-
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
- }
-
- kotlinOptions {
- jvmTarget = "11"
- }
-
- packagingOptions {
- exclude("META-INF/AL2.0")
- exclude("META-INF/LGPL2.1")
- }
-}
-
-jacoco {
- toolVersion = "0.8.7"
-}
-
-tasks {
- withType {
- kotlinOptions.jvmTarget = "11"
- kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
- kotlinOptions.freeCompilerArgs += "-Xexplicit-api=strict"
- }
-
- withType {
- reports {
- csv.isEnabled = false
- html.isEnabled = false
- }
- }
-}
-
-tasks.dokkaHtml {
- dokkaSourceSets {
- configureEach {
- offlineMode.set(true)
- }
- }
-}
diff --git a/buildSrc/src/main/java/java-library-module.gradle.kts b/buildSrc/src/main/java/java-library-module.gradle.kts
deleted file mode 100644
index 3584544..0000000
--- a/buildSrc/src/main/java/java-library-module.gradle.kts
+++ /dev/null
@@ -1,10 +0,0 @@
-plugins {
- id("org.jetbrains.kotlin.jvm")
- `java-library`
-}
-
-tasks {
- test {
- useJUnitPlatform()
- }
-}
diff --git a/buildSrc/src/main/java/release-module.gradle.kts b/buildSrc/src/main/java/release-module.gradle.kts
deleted file mode 100644
index 27852ad..0000000
--- a/buildSrc/src/main/java/release-module.gradle.kts
+++ /dev/null
@@ -1,9 +0,0 @@
-plugins {
- id("com.vanniktech.maven.publish")
-}
-
-val libraryVersion = System.getenv("BUILD_VERSION") ?: "0.0.1"
-
-mavenPublishing {
- version = libraryVersion
-}
diff --git a/context-aware/build.gradle.kts b/context-aware/build.gradle.kts
index a3db912..1ab02f6 100644
--- a/context-aware/build.gradle.kts
+++ b/context-aware/build.gradle.kts
@@ -1,14 +1,25 @@
+import com.kroger.gradle.config.junit5
+
plugins {
- id(Plugins.androidLibrary.id)
- id(Plugins.release.id)
+ alias(libs.plugins.conventions.publishedAndroidLibrary)
+}
+
+android {
+ namespace = "com.kroger.telemetry.contextaware"
+}
+
+kover {
+ currentProject {
+ createVariant("default") {
+ add("debug")
+ }
+ }
}
dependencies {
implementation(project(":telemetry"))
-
implementation(libs.injectJavax)
+ junit5()
testImplementation(libs.mockk)
- testImplementation(libs.jupiterApi)
- testRuntimeOnly(libs.jupiterEngine)
}
diff --git a/context-aware/src/main/AndroidManifest.xml b/context-aware/src/main/AndroidManifest.xml
deleted file mode 100644
index 3bc14e7..0000000
--- a/context-aware/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/context-aware/src/main/java/com/kroger/telemetry/contextaware/ContextAwareFacetResolver.kt b/context-aware/src/main/java/com/kroger/telemetry/contextaware/ContextAwareFacetResolver.kt
index acda674..ff18b02 100644
--- a/context-aware/src/main/java/com/kroger/telemetry/contextaware/ContextAwareFacetResolver.kt
+++ b/context-aware/src/main/java/com/kroger/telemetry/contextaware/ContextAwareFacetResolver.kt
@@ -30,8 +30,9 @@ import com.kroger.telemetry.facet.FacetResolver
import com.kroger.telemetry.facet.UnresolvedFacet
import javax.inject.Inject
-public class ContextAwareFacetResolver @Inject constructor(private val context: Context) :
- FacetResolver {
+public class ContextAwareFacetResolver @Inject constructor(
+ private val context: Context,
+) : FacetResolver {
override fun getType(): Class = ContextAwareFacet::class.java
override fun resolve(unresolvedFacet: UnresolvedFacet): List =
diff --git a/context-aware/src/test/java/com/kroger/telemetry/contextaware/ContextAwareFacetResolverTest.kt b/context-aware/src/test/java/com/kroger/telemetry/contextaware/ContextAwareFacetResolverTest.kt
index 319faf2..5c6b5c1 100644
--- a/context-aware/src/test/java/com/kroger/telemetry/contextaware/ContextAwareFacetResolverTest.kt
+++ b/context-aware/src/test/java/com/kroger/telemetry/contextaware/ContextAwareFacetResolverTest.kt
@@ -32,7 +32,6 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
public class ContextAwareFacetResolverTest {
-
private val context: Context = mockk()
private lateinit var contextAwareFacetResolver: ContextAwareFacetResolver
@@ -53,11 +52,10 @@ public class ContextAwareFacetResolverTest {
@Test
public fun `Given an ContextAwareFacetResolver, When resolve is called on a ContextAwareFacet, Then return the resolved Facet`() {
val testFacet = object : Facet {}
- val testUnresolvedFacet = object : ContextAwareFacet {
- override fun resolve(context: Context): Facet {
- return testFacet
+ val testUnresolvedFacet =
+ object : ContextAwareFacet {
+ override fun resolve(context: Context): Facet = testFacet
}
- }
val sut = contextAwareFacetResolver.resolve(testUnresolvedFacet)
diff --git a/firebase/build.gradle.kts b/firebase/build.gradle.kts
index c532450..1fdf7ad 100644
--- a/firebase/build.gradle.kts
+++ b/firebase/build.gradle.kts
@@ -1,31 +1,37 @@
+import com.kroger.gradle.config.junit5
+
plugins {
- id(Plugins.androidLibrary.id)
- id(Plugins.release.id)
+ alias(libs.plugins.conventions.publishedAndroidLibrary)
}
android {
- defaultConfig {
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ namespace = "com.kroger.telemetry.firebase"
+}
+
+kover {
+ currentProject {
+ createVariant("default") {
+ add("debug")
+ }
}
}
dependencies {
implementation(project(":telemetry"))
- implementation(libs.androidCoreKtx)
- implementation(libs.coroutines)
- implementation(libs.firebaseAnalytics)
+ implementation(libs.androidx.coreKtx)
+ implementation(libs.kotlinx.coroutinesCore)
+ implementation(platform(libs.firebase.bom))
+ implementation(libs.firebase.analytics)
implementation(libs.injectJavax)
- implementation(libs.stdLib)
+ junit5()
testImplementation(libs.mockk)
- testImplementation(libs.coroutinesTest)
- testImplementation(libs.jupiterApi)
- testRuntimeOnly(libs.jupiterEngine)
+ testImplementation(libs.kotlinx.coroutinesTest)
- androidTestImplementation(libs.androidxTestCore)
- androidTestImplementation(libs.androidxTestRules)
- androidTestImplementation(libs.androidxTestRunner)
- androidTestImplementation(libs.junit)
- androidTestImplementation(libs.junitTestKtx)
+ androidTestImplementation(libs.junit4)
+ androidTestImplementation(libs.androidx.test.core)
+ androidTestImplementation(libs.androidx.test.ext.junitKtx)
+ androidTestImplementation(libs.androidx.test.rules)
+ androidTestImplementation(libs.androidx.test.runner)
}
diff --git a/firebase/src/androidTest/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelayTest.kt b/firebase/src/androidTest/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelayTest.kt
index 9f273d4..b3ddf0a 100644
--- a/firebase/src/androidTest/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelayTest.kt
+++ b/firebase/src/androidTest/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelayTest.kt
@@ -1,3 +1,5 @@
+@file:Suppress("ktlint:standard:max-line-length")
+
package com.kroger.telemetry.firebase
import androidx.core.os.bundleOf
@@ -9,7 +11,6 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
internal class FirebaseAnalyticsRelayTest {
-
@Test
fun given_event_with_firebase_facet_with_data_WHEN_recorded_THEN_data_matches_in_logged_event() =
runBlocking {
@@ -19,11 +20,12 @@ internal class FirebaseAnalyticsRelayTest {
val val1 = "val1"
val val2 = 2
- val facetWithData = object : DeveloperMetricsFacet {
- override val eventName: String = fakeName
- override val compute: () -> Map =
- { mapOf(key1 to val1, key2 to val2) }
- }
+ val facetWithData =
+ object : DeveloperMetricsFacet {
+ override val eventName: String = fakeName
+ override val compute: () -> Map =
+ { mapOf(key1 to val1, key2 to val2) }
+ }
val bundleToCompare = bundleOf(key1 to val1, key2 to val2)
diff --git a/firebase/src/main/AndroidManifest.xml b/firebase/src/main/AndroidManifest.xml
deleted file mode 100644
index 360f88f..0000000
--- a/firebase/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/firebase/src/main/java/com/kroger/telemetry/firebase/CrashlyticsWrapper.kt b/firebase/src/main/java/com/kroger/telemetry/firebase/CrashlyticsWrapper.kt
index f673dff..dcbc831 100644
--- a/firebase/src/main/java/com/kroger/telemetry/firebase/CrashlyticsWrapper.kt
+++ b/firebase/src/main/java/com/kroger/telemetry/firebase/CrashlyticsWrapper.kt
@@ -32,7 +32,6 @@ package com.kroger.telemetry.firebase
* @sample crashlyticsWrapperImplementation
*/
public interface CrashlyticsWrapper {
-
/**
* Records a custom key and value to be associated with subsequent fatal and non-fatal reports. Multiple calls to this method
* with the same key will update the value for that key. The value of any key at the time of a fatal or non-fatal event will
@@ -44,7 +43,10 @@ public interface CrashlyticsWrapper {
*
*@param value A value to be associated with the given key
*/
- public fun setCustomKey(key: String, value: String)
+ public fun setCustomKey(
+ key: String,
+ value: String,
+ )
/**
* Records a custom key and value to be associated with subsequent fatal and non-fatal reports. Multiple calls to this method
@@ -57,7 +59,10 @@ public interface CrashlyticsWrapper {
*
*@param value A value to be associated with the given key
*/
- public fun setCustomKey(key: String, value: Boolean)
+ public fun setCustomKey(
+ key: String,
+ value: Boolean,
+ )
/**
* Records a custom key and value to be associated with subsequent fatal and non-fatal reports. Multiple calls to this method
@@ -70,7 +75,10 @@ public interface CrashlyticsWrapper {
*
*@param value A value to be associated with the given key
*/
- public fun setCustomKey(key: String, value: Int)
+ public fun setCustomKey(
+ key: String,
+ value: Int,
+ )
/**
* Records a custom key and value to be associated with subsequent fatal and non-fatal reports. Multiple calls to this method
@@ -83,7 +91,10 @@ public interface CrashlyticsWrapper {
*
*@param value A value to be associated with the given key
*/
- public fun setCustomKey(key: String, value: Long)
+ public fun setCustomKey(
+ key: String,
+ value: Long,
+ )
/**
* Records a custom key and value to be associated with subsequent fatal and non-fatal reports. Multiple calls to this method
@@ -96,7 +107,10 @@ public interface CrashlyticsWrapper {
*
*@param value A value to be associated with the given key
*/
- public fun setCustomKey(key: String, value: Float)
+ public fun setCustomKey(
+ key: String,
+ value: Float,
+ )
/**
* Records a custom key and value to be associated with subsequent fatal and non-fatal reports. Multiple calls to this method
@@ -109,7 +123,10 @@ public interface CrashlyticsWrapper {
*
*@param value A value to be associated with the given key
*/
- public fun setCustomKey(key: String, value: Double)
+ public fun setCustomKey(
+ key: String,
+ value: Double,
+ )
/**
* Records a non-fatal report to send to Crashlytics.
diff --git a/firebase/src/main/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelay.kt b/firebase/src/main/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelay.kt
index 776cba2..3540287 100644
--- a/firebase/src/main/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelay.kt
+++ b/firebase/src/main/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelay.kt
@@ -40,9 +40,9 @@ import javax.inject.Inject
public class FirebaseAnalyticsRelay @Inject constructor(
private val firebaseAnalytics: FirebaseAnalytics,
) : Relay by Relay.buildTypedRelay(
- { facet ->
- firebaseAnalytics.logEvent(facet.eventName, facet.compute()?.toBundle())
- },
-)
+ { facet ->
+ firebaseAnalytics.logEvent(facet.eventName, facet.compute()?.toBundle())
+ },
+ )
internal fun Map.toBundle(): Bundle = bundleOf(*this.toList().toTypedArray())
diff --git a/firebase/src/main/java/com/kroger/telemetry/firebase/FirebaseCrashlyticsRelay.kt b/firebase/src/main/java/com/kroger/telemetry/firebase/FirebaseCrashlyticsRelay.kt
index d36b1a2..26ba3be 100644
--- a/firebase/src/main/java/com/kroger/telemetry/firebase/FirebaseCrashlyticsRelay.kt
+++ b/firebase/src/main/java/com/kroger/telemetry/firebase/FirebaseCrashlyticsRelay.kt
@@ -52,8 +52,9 @@ import javax.inject.Inject
*
* @sample crashlyticsWrapperImplementation
*/
-public class FirebaseCrashlyticsRelay @Inject constructor(private val crashlytics: CrashlyticsWrapper) : Relay {
-
+public class FirebaseCrashlyticsRelay @Inject constructor(
+ private val crashlytics: CrashlyticsWrapper,
+) : Relay {
override suspend fun process(event: Event) {
event.facets.filterIsInstance().forEach {
when (it) {
@@ -102,8 +103,9 @@ public class FirebaseCrashlyticsRelay @Inject constructor(private val crashlytic
*
* NOTE: Crashlytics supports up to 64 key/value pairs in a single report. Each key/value pair must be no larger than 1 kB in size.
*/
-public sealed class CrashlyticsKey(public val key: String) : Facet {
-
+public sealed class CrashlyticsKey(
+ public val key: String,
+) : Facet {
public companion object {
/**
* Builds a [CrashlyticsKey] for the key/value pair.
@@ -111,7 +113,10 @@ public sealed class CrashlyticsKey(public val key: String) : Facet {
* @param key a unique key to identify the value
* @param value a String value
*/
- public fun build(key: String, value: String): CrashlyticsKey = StringState(key, value)
+ public fun build(
+ key: String,
+ value: String,
+ ): CrashlyticsKey = StringState(key, value)
/**
* Builds a [CrashlyticsKey] for the key/value pair.
@@ -119,7 +124,10 @@ public sealed class CrashlyticsKey(public val key: String) : Facet {
* @param key a unique key to identify the value
* @param value a Boolean value
*/
- public fun build(key: String, value: Boolean): CrashlyticsKey = BooleanState(key, value)
+ public fun build(
+ key: String,
+ value: Boolean,
+ ): CrashlyticsKey = BooleanState(key, value)
/**
* Builds a [CrashlyticsKey] for the key/value pair.
@@ -127,7 +135,10 @@ public sealed class CrashlyticsKey(public val key: String) : Facet {
* @param key a unique key to identify the value
* @param value an Int value
*/
- public fun build(key: String, value: Int): CrashlyticsKey = IntState(key, value)
+ public fun build(
+ key: String,
+ value: Int,
+ ): CrashlyticsKey = IntState(key, value)
/**
* Builds a [CrashlyticsKey] for the key/value pair.
@@ -135,7 +146,10 @@ public sealed class CrashlyticsKey(public val key: String) : Facet {
* @param key a unique key to identify the value
* @param value a Long value
*/
- public fun build(key: String, value: Long): CrashlyticsKey = LongState(key, value)
+ public fun build(
+ key: String,
+ value: Long,
+ ): CrashlyticsKey = LongState(key, value)
/**
* Builds a [CrashlyticsKey] for the key/value pair.
@@ -143,7 +157,10 @@ public sealed class CrashlyticsKey(public val key: String) : Facet {
* @param key a unique key to identify the value
* @param value a Float value
*/
- public fun build(key: String, value: Float): CrashlyticsKey = FloatState(key, value)
+ public fun build(
+ key: String,
+ value: Float,
+ ): CrashlyticsKey = FloatState(key, value)
/**
* Builds a [CrashlyticsKey] for the key/value pair.
@@ -151,7 +168,10 @@ public sealed class CrashlyticsKey(public val key: String) : Facet {
* @param key a unique key to identify the value
* @param value a Double value
*/
- public fun build(key: String, value: Double): CrashlyticsKey = DoubleState(key, value)
+ public fun build(
+ key: String,
+ value: Double,
+ ): CrashlyticsKey = DoubleState(key, value)
}
}
@@ -159,9 +179,32 @@ public sealed class CrashlyticsKey(public val key: String) : Facet {
* These classes keep the key/value pairs typesafe, while the CrashlyticsKey build methods keep the public API
* simple, i.e. CrashlyticsKey.build(key, value).
*/
-private class StringState(key: String, val value: String) : CrashlyticsKey(key)
-private class BooleanState(key: String, val value: Boolean) : CrashlyticsKey(key)
-private class IntState(key: String, val value: Int) : CrashlyticsKey(key)
-private class LongState(key: String, val value: Long) : CrashlyticsKey(key)
-private class FloatState(key: String, val value: Float) : CrashlyticsKey(key)
-private class DoubleState(key: String, val value: Double) : CrashlyticsKey(key)
+private class StringState(
+ key: String,
+ val value: String,
+) : CrashlyticsKey(key)
+
+private class BooleanState(
+ key: String,
+ val value: Boolean,
+) : CrashlyticsKey(key)
+
+private class IntState(
+ key: String,
+ val value: Int,
+) : CrashlyticsKey(key)
+
+private class LongState(
+ key: String,
+ val value: Long,
+) : CrashlyticsKey(key)
+
+private class FloatState(
+ key: String,
+ val value: Float,
+) : CrashlyticsKey(key)
+
+private class DoubleState(
+ key: String,
+ val value: Double,
+) : CrashlyticsKey(key)
diff --git a/firebase/src/main/java/com/kroger/telemetry/firebase/Samples.kt b/firebase/src/main/java/com/kroger/telemetry/firebase/Samples.kt
index b53f933..c7e1b99 100644
--- a/firebase/src/main/java/com/kroger/telemetry/firebase/Samples.kt
+++ b/firebase/src/main/java/com/kroger/telemetry/firebase/Samples.kt
@@ -32,8 +32,13 @@ import javax.inject.Inject
* This serves to make the `RealCrashlytics` sample below compile without crashlytics on the classpath
*/
private interface FirebaseCrashlytics {
- fun setCustomKey(key: String, value: Any)
+ fun setCustomKey(
+ key: String,
+ value: Any,
+ )
+
fun recordException(e: Throwable)
+
fun log(message: String)
}
@@ -42,29 +47,48 @@ internal object Samples {
* A sample of how one might implement [CrashlyticsWrapper] to forward calls to the real thing
*/
internal fun crashlyticsWrapperImplementation() {
- class RealCrashlytics @Inject constructor(private val crashlytics: FirebaseCrashlytics) :
- CrashlyticsWrapper {
- override fun setCustomKey(key: String, value: String) {
+ class RealCrashlytics @Inject constructor(
+ private val crashlytics: FirebaseCrashlytics,
+ ) : CrashlyticsWrapper {
+ override fun setCustomKey(
+ key: String,
+ value: String,
+ ) {
crashlytics.setCustomKey(key, value)
}
- override fun setCustomKey(key: String, value: Boolean) {
+ override fun setCustomKey(
+ key: String,
+ value: Boolean,
+ ) {
crashlytics.setCustomKey(key, value)
}
- override fun setCustomKey(key: String, value: Int) {
+ override fun setCustomKey(
+ key: String,
+ value: Int,
+ ) {
crashlytics.setCustomKey(key, value)
}
- override fun setCustomKey(key: String, value: Long) {
+ override fun setCustomKey(
+ key: String,
+ value: Long,
+ ) {
crashlytics.setCustomKey(key, value)
}
- override fun setCustomKey(key: String, value: Float) {
+ override fun setCustomKey(
+ key: String,
+ value: Float,
+ ) {
crashlytics.setCustomKey(key, value)
}
- override fun setCustomKey(key: String, value: Double) {
+ override fun setCustomKey(
+ key: String,
+ value: Double,
+ ) {
crashlytics.setCustomKey(key, value)
}
diff --git a/firebase/src/test/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelayTest.kt b/firebase/src/test/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelayTest.kt
index 19dbea2..bb7923e 100644
--- a/firebase/src/test/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelayTest.kt
+++ b/firebase/src/test/java/com/kroger/telemetry/firebase/FirebaseAnalyticsRelayTest.kt
@@ -33,8 +33,7 @@ import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import io.mockk.verify
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
internal class FirebaseAnalyticsRelayTest {
@@ -47,10 +46,9 @@ internal class FirebaseAnalyticsRelayTest {
override val eventName: String = fakeName
}
- @OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `GIVEN event with firebase facet WHEN recorded THEN name matches in logged event`() =
- runBlockingTest {
+ runTest {
every { mockFirebaseAnalytics.logEvent(any(), any()) } just runs
firebaseAnalyticsRelay.process(
diff --git a/firebase/src/test/java/com/kroger/telemetry/firebase/FirebaseCrashlyticsRelayTest.kt b/firebase/src/test/java/com/kroger/telemetry/firebase/FirebaseCrashlyticsRelayTest.kt
index 298cafd..d636955 100644
--- a/firebase/src/test/java/com/kroger/telemetry/firebase/FirebaseCrashlyticsRelayTest.kt
+++ b/firebase/src/test/java/com/kroger/telemetry/firebase/FirebaseCrashlyticsRelayTest.kt
@@ -35,7 +35,6 @@ import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Test
internal class FirebaseCrashlyticsRelayTest {
-
private val mockCrashlytics = mockk(relaxed = true)
private val relay = FirebaseCrashlyticsRelay(mockCrashlytics)
@@ -68,14 +67,15 @@ internal class FirebaseCrashlyticsRelayTest {
runBlocking {
relay.process(
TestEvent(
- keys = arrayOf(
- CrashlyticsKey.build("STRING", "hello-crashlytics"),
- CrashlyticsKey.build("BOOLEAN", true),
- CrashlyticsKey.build("INT", 42),
- CrashlyticsKey.build("LONG", 42L),
- CrashlyticsKey.build("FLOAT", 4.2f),
- CrashlyticsKey.build("DOUBLE", 4.2),
- ),
+ keys =
+ arrayOf(
+ CrashlyticsKey.build("STRING", "hello-crashlytics"),
+ CrashlyticsKey.build("BOOLEAN", true),
+ CrashlyticsKey.build("INT", 42),
+ CrashlyticsKey.build("LONG", 42L),
+ CrashlyticsKey.build("FLOAT", 4.2f),
+ CrashlyticsKey.build("DOUBLE", 4.2),
+ ),
),
)
}
@@ -116,12 +116,13 @@ internal class FirebaseCrashlyticsRelayTest {
val e1 = RuntimeException("Oh no")
val key = "some key"
val value = "some value"
- val event = TestEvent(
- message = testMessage,
- significance = Significance.ERROR,
- throwable = e1,
- keys = arrayOf(CrashlyticsKey.build(key, value)),
- )
+ val event =
+ TestEvent(
+ message = testMessage,
+ significance = Significance.ERROR,
+ throwable = e1,
+ keys = arrayOf(CrashlyticsKey.build(key, value)),
+ )
runBlocking { relay.process(event) }
@@ -142,11 +143,11 @@ internal class FirebaseCrashlyticsRelayTest {
get() = message ?: ""
override val facets: List
- get() = (
- listOf(significance) +
- keys +
- throwable?.let { Failure(throwable = it) }
- )
- .filterNotNull()
+ get() =
+ (
+ listOf(significance) +
+ keys +
+ throwable?.let { Failure(throwable = it) }
+ ).filterNotNull()
}
}
diff --git a/gradle.properties b/gradle.properties
index 029522e..bcd73ca 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -18,6 +18,13 @@ android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
+## Kroger Gradle Plugin Properties
+kgp.android.autoconfigure.compose=false
+kgp.android.autoconfigure.hilt.application=false
+
+# Ignore v1 deprecation warning since v2 is still experimental
+org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true
+
## Publishing Properties
SONATYPE_HOST=DEFAULT
RELEASE_SIGNING_ENABLED=true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 8505da2..6283b3f 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,50 +1,83 @@
[versions]
-androidTest = "1.4.0"
-coroutines = "1.5.0"
-junit4 = "4.13.1"
-junit5 = "5.7.1"
-kotlin = "1.5.31"
-mockk = "1.12.0"
-serialize = "1.2.2"
+androidGradlePlugin = "8.10.0"
+androidJunit5Plugin = "1.12.0.0"
+androidMaterial = "1.12.0"
+androidxAppCompat = "1.7.0"
+androidxConstraintLayout = "2.2.1"
+androidxCore = "1.16.0"
+androidxTestCore = "1.6.1"
+androidxTestEspresso = "3.6.1"
+androidxTestExtJunit = "1.2.1"
+androidxTestRules = "1.6.1"
+androidxTestRunner = "1.6.2"
+conventionPlugin = "2.0.0-alpha.4"
+dependencyAnalysis = "2.17.0"
+firebaseBom = "32.8.0"
+gradleMavenPublishPlugin = "0.31.0"
+gradleVersions = "0.51.0"
+javaxInject = "1"
+kgpCompileSdk = "35"
+kgpDagger = "2.56.1"
+kgpAndroidDesugarJdkLibs = "2.1.5"
+kgpAndroidxComposeBom = "2025.05.00"
+kgpDokka = "2.0.0"
+kgpJdk = "24"
+kgpJvmTarget = "11"
+kgpJunit4 = "4.13.2"
+kgpJunitBom = "5.12.2"
+kgpMinSdk = "24"
+kgpTargetSdk = "35"
+kotlin = "2.1.20"
+kotlinter = "5.0.2"
+kotlinxCoroutines = "1.10.2"
+kover = "0.9.1"
+ksp = "2.1.20-1.0.32"
+mockk = "1.14.2"
[libraries]
# android
-androidCoreKtx = { module = "androidx.core:core-ktx", version = "1.8.0" }
-annotation = { module = "androidx.annotation:annotation", version = "1.0.0" }
-appCompat = { module = "androidx.appcompat:appcompat", version = "1.4.1" }
-contraintLayount = { module = "androidx.constraintlayout:constraintlayout", version = "2.1.3" }
-googleMaterial = { module = "com.google.android.material:material", version = "1.5.0" }
-
-# dagger (sample app only)
-hilt = { module = "com.google.dagger:hilt-android", version = "2.41" }
-hiltAndroidCompiler = { module = "com.google.dagger:hilt-android-compiler", version = "2.41" }
-hiltCompiler = { module = "androidx.hilt:hilt-compiler", version = "1.0.0" }
+android-material = { module = "com.google.android.material:material", version.ref = "androidMaterial" }
+androidx-constrainlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidxConstraintLayout" }
+androidx-coreKtx = { module = "androidx.core:core-ktx", version.ref = "androidxCore" }
+androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidxAppCompat" }
# firebase
-firebaseAnalytics = { module = "com.google.firebase:firebase-analytics", version = "19.0.0" }
+firebase-analytics = { module = "com.google.firebase:firebase-analytics" }
+firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
# kotlin
-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
-coroutinesAndroid = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
-coroutinesTest = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
+kotlinx-coroutinesCore = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
+kotlinx-coroutinesAndroid = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutines" }
+kotlinx-coroutinesTest = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" }
kotlinTest = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialize" }
-stdLib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "kotlin" }
# other
-injectJavax = { module = "javax.inject:javax.inject", version = "1" }
+injectJavax = { module = "javax.inject:javax.inject", version.ref = "javaxInject" }
## unit tests
-jupiterApi = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit5" }
-jupiterEngine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit5" }
-androidJunitTestExt = { module = "androidx.test.ext:junit", version = "1.1.3" }
+android-test-espressoCore = { module = "androidx.test.espresso:espresso-core", version.ref = "androidxTestEspresso" }
+junit4 = { module = "junit:junit", version.ref = "kgpJunit4" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
-textEspresso = { module = "androidx.test.espresso:espresso-core", version = "3.4.0" }
-truth = { module = "com.google.truth:truth", version = "1.1" }
# instrumented tests
-androidxTestCore = { module = "androidx.test:core", version = "1.4.1-alpha07" }
-androidxTestRules = { module = "androidx.test:rules", version.ref = "androidTest" }
-androidxTestRunner = { module = "androidx.test:runner", version.ref = "androidTest" }
-junit = { module = "junit:junit", version.ref = "junit4" }
-junitTestKtx = { module = "androidx.test.ext:junit-ktx", version = "1.1.2" }
+androidx-test-core = { module = "androidx.test:core", version.ref = "androidxTestCore" }
+androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidxTestRules" }
+androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidxTestRunner" }
+androidx-test-ext-junitKtx = { module = "androidx.test.ext:junit-ktx", version.ref = "androidxTestExtJunit" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
+android-junit5 = { id = "de.mannodermaus.android-junit5", version.ref = "androidJunit5Plugin" }
+compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
+conventions-androidApplication = { id = "com.kroger.gradle.android-application-conventions", version.ref = "conventionPlugin" }
+conventions-publishedAndroidLibrary = { id = "com.kroger.gradle.published-android-library-conventions", version.ref = "conventionPlugin" }
+conventions-publishedKotlinLibrary = { id = "com.kroger.gradle.published-kotlin-library-conventions", version.ref = "conventionPlugin" }
+conventions-root = { id = "com.kroger.gradle.root", version.ref = "conventionPlugin" }
+dagger-hilt = { id = "com.google.dagger.hilt.android", version.ref = "kgpDagger" }
+dependencyAnalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysis" }
+dokka = { id = "org.jetbrains.dokka", version.ref = "kgpDokka" }
+gradleVersions = { id = "com.github.ben-manes.versions", version.ref = "gradleVersions" }
+kotlinter = { id = "org.jmailen.kotlinter", version.ref = "kotlinter" }
+kotlinx-kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
+ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
+mavenPublish = { id = "com.vanniktech.maven.publish", version.ref = "gradleMavenPublishPlugin" }
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index f6b961f..1b33c55 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index ee8007b..ca025c8 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
-#Fri Dec 04 09:19:29 PST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
diff --git a/gradlew b/gradlew
index cccdd3d..23d15a9 100755
--- a/gradlew
+++ b/gradlew
@@ -1,78 +1,129 @@
-#!/usr/bin/env sh
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+CLASSPATH="\\\"\\\""
+
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -81,92 +132,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
fi
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
fi
- i=$((i+1))
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
done
- case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
fi
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index e95643d..5eed7ee 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,4 +1,22 @@
-@if "%DEBUG%" == "" @echo off
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
+
+@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -9,25 +27,29 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if %ERRORLEVEL% equ 0 goto execute
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -35,48 +57,36 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
:execute
@rem Setup the command line
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+set CLASSPATH=
+
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
+if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts
index f97477f..c844d19 100644
--- a/sample/build.gradle.kts
+++ b/sample/build.gradle.kts
@@ -1,39 +1,19 @@
-plugins {
- id("com.android.application")
- id("kotlin-android")
- kotlin("kapt")
- id("dagger.hilt.android.plugin")
-}
+import com.kroger.gradle.config.hiltKsp
-kapt {
- correctErrorTypes = true
+plugins {
+ alias(libs.plugins.conventions.androidApplication)
+ alias(libs.plugins.dagger.hilt)
+ alias(libs.plugins.ksp)
}
android {
- compileSdk = (SdkVersions.compileSdkVersion)
- buildToolsVersion = ("30.0.3")
namespace = "com.kroger.telemetry.sample"
- defaultConfig {
- minSdk = (SdkVersions.minSdkVersion)
- targetSdk = (SdkVersions.targetSdkVersion)
- compileSdk = (SdkVersions.compileSdkVersion)
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
- }
-
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
- }
-
- kotlinOptions {
- jvmTarget = "11"
- }
buildFeatures {
viewBinding = true
@@ -48,17 +28,14 @@ dependencies {
implementation(project(":android"))
implementation(project(":context-aware"))
- implementation(libs.androidCoreKtx)
- implementation(libs.appCompat)
- implementation(libs.contraintLayount)
- implementation(libs.coroutines)
- implementation(libs.googleMaterial)
- implementation(libs.stdLib)
+ implementation(libs.androidx.appcompat)
+ implementation(libs.androidx.constrainlayout)
+ implementation(libs.androidx.coreKtx)
+ implementation(libs.kotlinx.coroutinesCore)
+ implementation(libs.android.material)
- implementation(libs.hilt)
- kapt(libs.hiltAndroidCompiler)
- kapt(libs.hiltCompiler)
+ hiltKsp()
- androidTestImplementation(libs.androidJunitTestExt)
- androidTestImplementation(libs.textEspresso)
+ androidTestImplementation(libs.android.test.espressoCore)
+ androidTestImplementation(libs.androidx.test.ext.junitKtx)
}
diff --git a/sample/src/main/java/com/kroger/telemetry/sample/AppTelemeter.kt b/sample/src/main/java/com/kroger/telemetry/sample/AppTelemeter.kt
index 9d4283b..0119e29 100644
--- a/sample/src/main/java/com/kroger/telemetry/sample/AppTelemeter.kt
+++ b/sample/src/main/java/com/kroger/telemetry/sample/AppTelemeter.kt
@@ -36,9 +36,10 @@ class AppTelemeter @Inject constructor(
private val context: Context,
private val contextAwareFacetResolver: ContextAwareFacetResolver,
) : Telemeter by Telemeter.build(
- relays = listOf(LogRelay(), BarRelay(), FooRelay(), ToastRelay(context)),
- facetResolvers = mapOf(
- contextAwareFacetResolver.getType() to contextAwareFacetResolver,
- ),
- facets = listOf(Prefix.App("sample")),
-)
+ relays = listOf(LogRelay(), BarRelay(), FooRelay(), ToastRelay(context)),
+ facetResolvers =
+ mapOf(
+ contextAwareFacetResolver.getType() to contextAwareFacetResolver,
+ ),
+ facets = listOf(Prefix.App("sample")),
+ )
diff --git a/sample/src/main/java/com/kroger/telemetry/sample/BarRelay.kt b/sample/src/main/java/com/kroger/telemetry/sample/BarRelay.kt
index f7a012f..75ae602 100644
--- a/sample/src/main/java/com/kroger/telemetry/sample/BarRelay.kt
+++ b/sample/src/main/java/com/kroger/telemetry/sample/BarRelay.kt
@@ -30,6 +30,7 @@ import com.kroger.telemetry.facet.Facet
class BarRelay : TypedRelay {
override val type: Class = BarFacet::class.java
+
override suspend fun processFacet(facet: BarFacet) {
val string =
"completed bar facet ${facet.data}"
@@ -37,4 +38,6 @@ class BarRelay : TypedRelay {
}
}
-data class BarFacet(val data: String) : Facet
+data class BarFacet(
+ val data: String,
+) : Facet
diff --git a/sample/src/main/java/com/kroger/telemetry/sample/MainActivity.kt b/sample/src/main/java/com/kroger/telemetry/sample/MainActivity.kt
index fdf09f2..8a7a9fe 100644
--- a/sample/src/main/java/com/kroger/telemetry/sample/MainActivity.kt
+++ b/sample/src/main/java/com/kroger/telemetry/sample/MainActivity.kt
@@ -26,6 +26,7 @@ package com.kroger.telemetry.sample
import android.os.Bundle
import android.util.Log
+import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import com.kroger.telemetry.Event
import com.kroger.telemetry.Relay
@@ -45,7 +46,6 @@ import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
-
private val binding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
@@ -54,6 +54,7 @@ class MainActivity : AppCompatActivity() {
lateinit var telemeter: ModuleOneTelemeter
override fun onCreate(savedInstanceState: Bundle?) {
+ enableEdgeToEdge()
super.onCreate(savedInstanceState)
setContentView(binding.root)
@@ -84,24 +85,28 @@ class MainActivity : AppCompatActivity() {
}
sealed class ActivityEvent : Event {
- protected val activityFacets = listOf(
- BarFacet("some bar:data from the activity"),
- )
+ protected val activityFacets =
+ listOf(
+ BarFacet("some bar:data from the activity"),
+ )
object Created : ActivityEvent() {
override val description = "Activity Created"
override val facets = activityFacets
}
- class ButtonClicked(buttonTag: String) : ActivityEvent() {
+ class ButtonClicked(
+ buttonTag: String,
+ ) : ActivityEvent() {
override val description: String = "$buttonTag clicked"
override val facets: List =
- activityFacets + listOf(
- StringResourceFormattedToastFacet(
- R.string.button_click_message,
- buttonTag,
- ),
- )
+ activityFacets +
+ listOf(
+ StringResourceFormattedToastFacet(
+ R.string.button_click_message,
+ buttonTag,
+ ),
+ )
}
}
@@ -118,11 +123,13 @@ class ActivityRelay : Relay {
class ModuleOneTelemeter(
telemeter: Telemeter,
contextAwareFacetResolver: ContextAwareFacetResolver,
-) :
- Telemeter by telemeter.child(
+) : Telemeter by telemeter.child(
relays = listOf(ActivityRelay()),
facets = listOf(MainActivity.prefix),
- facetResolvers = mapOf(StringResourceFormattedToastFacet::class.java to contextAwareFacetResolver),
+ facetResolvers =
+ mapOf(
+ StringResourceFormattedToastFacet::class.java to contextAwareFacetResolver,
+ ),
)
@InstallIn(ActivityComponent::class)
@@ -132,6 +139,5 @@ object ModuleOneModule {
fun provideModuleOneTelemeter(
appTelemeter: AppTelemeter,
contextAwareFacetResolver: ContextAwareFacetResolver,
- ): ModuleOneTelemeter =
- ModuleOneTelemeter(appTelemeter, contextAwareFacetResolver)
+ ): ModuleOneTelemeter = ModuleOneTelemeter(appTelemeter, contextAwareFacetResolver)
}
diff --git a/sample/src/main/java/com/kroger/telemetry/sample/SampleApplication.kt b/sample/src/main/java/com/kroger/telemetry/sample/SampleApplication.kt
index 4bc5fce..31e49e4 100644
--- a/sample/src/main/java/com/kroger/telemetry/sample/SampleApplication.kt
+++ b/sample/src/main/java/com/kroger/telemetry/sample/SampleApplication.kt
@@ -48,7 +48,10 @@ class SampleApplication : Application() {
}
}
-data class ApplicationStartupEvent(val message: String, val toast: Boolean = false) : Event {
+data class ApplicationStartupEvent(
+ val message: String,
+ val toast: Boolean = false,
+) : Event {
override val description = message
override val facets: List = if (!toast) listOf() else listOf(ToastFacet(message))
}
@@ -57,5 +60,7 @@ data class ApplicationStartupEvent(val message: String, val toast: Boolean = fal
@Module
object TelemeterModule {
@Provides
- fun provideContext(@ApplicationContext context: Context): Context = context
+ fun provideContext(
+ @ApplicationContext context: Context,
+ ): Context = context
}
diff --git a/sample/src/main/java/com/kroger/telemetry/sample/StringResourceFormattedToastFacet.kt b/sample/src/main/java/com/kroger/telemetry/sample/StringResourceFormattedToastFacet.kt
index 017aafd..170cc29 100644
--- a/sample/src/main/java/com/kroger/telemetry/sample/StringResourceFormattedToastFacet.kt
+++ b/sample/src/main/java/com/kroger/telemetry/sample/StringResourceFormattedToastFacet.kt
@@ -34,7 +34,5 @@ class StringResourceFormattedToastFacet(
@StringRes private val resId: Int,
private vararg val formatArgs: String,
) : ContextAwareFacet {
- override fun resolve(context: Context): Facet {
- return ToastFacet(context.getString(resId, *formatArgs))
- }
+ override fun resolve(context: Context): Facet = ToastFacet(context.getString(resId, *formatArgs))
}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 9c65401..e586986 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -3,36 +3,20 @@ include(":android")
include(":context-aware")
include(":firebase")
include(":sample")
-enableFeaturePreview("VERSION_CATALOGS")
rootProject.name = "telemetry"
pluginManagement {
repositories {
mavenCentral()
google()
-
- // Public portal required for ben-manes:version
gradlePluginPortal()
}
- plugins {
- id("de.mannodermaus.android-junit5").version("1.8.0.0")
- id("org.jetbrains.dokka").version("1.5.31")
- id("com.android.application").version("7.3.0")
- id("org.jetbrains.kotlin.plugin.serialization").version("1.5.31")
- id("com.vanniktech.maven.publish").version("0.24.0")
- }
+}
- resolutionStrategy {
- eachPlugin {
- when (requested.id.id) {
- "dagger.hilt.android.plugin" -> useModule("com.google.dagger:hilt-android-gradle-plugin:2.40.5")
- "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31")
- }
- }
- dependencyResolutionManagement {
- versionCatalogs {
- (files("gradle/libs.versions.toml"))
- }
- }
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
}
}
diff --git a/telemetry/build.gradle.kts b/telemetry/build.gradle.kts
index 6108010..b8ade36 100644
--- a/telemetry/build.gradle.kts
+++ b/telemetry/build.gradle.kts
@@ -1,12 +1,21 @@
+import com.kroger.gradle.config.junit5
+
plugins {
- id(Plugins.javaLibrary.id)
- id(Plugins.release.id)
+ alias(libs.plugins.conventions.publishedKotlinLibrary)
+}
+
+kover {
+ currentProject {
+ createVariant("default") {
+ add("jvm")
+ }
+ }
}
dependencies {
- implementation(libs.coroutines)
- implementation(libs.stdLib)
+ implementation(libs.kotlinx.coroutinesCore)
- testImplementation(libs.coroutinesTest)
+ junit5()
+ testImplementation(libs.kotlinx.coroutinesTest)
testImplementation(libs.kotlinTest)
}
diff --git a/telemetry/src/main/java/com/kroger/telemetry/Event.kt b/telemetry/src/main/java/com/kroger/telemetry/Event.kt
index df4faee..5fc69fd 100644
--- a/telemetry/src/main/java/com/kroger/telemetry/Event.kt
+++ b/telemetry/src/main/java/com/kroger/telemetry/Event.kt
@@ -36,6 +36,8 @@ import com.kroger.telemetry.facet.Facet
* @property facets A list of data and metadata pertinent to the event.
*/
public interface Event {
- public val description: String get() = "${this::class.java.simpleName}\n${facets.joinToString("\n")}"
+ public val description: String get() = "${this::class.java.simpleName}\n${facets.joinToString(
+ "\n",
+ )}"
public val facets: List
}
diff --git a/telemetry/src/main/java/com/kroger/telemetry/Relay.kt b/telemetry/src/main/java/com/kroger/telemetry/Relay.kt
index 5737ab8..31a601a 100644
--- a/telemetry/src/main/java/com/kroger/telemetry/Relay.kt
+++ b/telemetry/src/main/java/com/kroger/telemetry/Relay.kt
@@ -60,6 +60,7 @@ public interface Relay {
*/
public interface TypedRelay : Relay {
public val type: Class
+
override suspend fun process(event: Event) {
event.facets.filterIsInstance(type).forEach { facet ->
processFacet(facet)
diff --git a/telemetry/src/main/java/com/kroger/telemetry/Samples.kt b/telemetry/src/main/java/com/kroger/telemetry/Samples.kt
index 84dc843..2470ee8 100644
--- a/telemetry/src/main/java/com/kroger/telemetry/Samples.kt
+++ b/telemetry/src/main/java/com/kroger/telemetry/Samples.kt
@@ -29,32 +29,45 @@ import com.kroger.telemetry.facet.Prefix
import com.kroger.telemetry.facet.Significance
import com.kroger.telemetry.relay.PrintRelay
-private data class MyDataType(val data: String)
+private data class MyDataType(
+ val data: String,
+)
internal fun topLevelExample() {
- data class MyFacet(override val compute: () -> MyDataType) : Facet.Computed
+ data class MyFacet(
+ override val compute: () -> MyDataType,
+ ) : Facet.Computed
- data class MyEvent(val thingThatHappened: String) : Event {
+ data class MyEvent(
+ val thingThatHappened: String,
+ ) : Event {
override val description: String = thingThatHappened
- override val facets: List = listOf(
- Significance.INFORMATIONAL,
- MyFacet { /* expensive logic that results in */ MyDataType(thingThatHappened) },
- /* other facets for other relays */
- )
+ override val facets: List =
+ listOf(
+ Significance.INFORMATIONAL,
+ MyFacet {
+ // expensive logic that results in
+ MyDataType(thingThatHappened)
+ },
+ // other facets for other relays
+ )
}
class MyRelay : TypedRelay {
override val type: Class = MyFacet::class.java
+
override suspend fun processFacet(facet: MyFacet) {
- /* do something with */ facet.compute().data
+ // do something with
+ facet.compute().data
}
}
- /* Make appTelemeter available to your application */
- val appTelemeter = Telemeter.build(
- relays = listOf(MyRelay()),
- facets = listOf(Prefix.App("My Application Name")),
- )
+ // Make appTelemeter available to your application
+ val appTelemeter =
+ Telemeter.build(
+ relays = listOf(MyRelay()),
+ facets = listOf(Prefix.App("My Application Name")),
+ )
fun onThingHappened() {
appTelemeter.record(MyEvent("a thing happened"))
@@ -67,12 +80,16 @@ internal fun childTelemeterSample(parentTelemeter: Telemeter) {
}
internal fun createTypedRelay() {
- data class MyFacet(val myValue: String) : Facet
- class MyTypedRelay : TypedRelay by Relay.buildTypedRelay(
- { myFacet ->
- myFacet.myValue
- },
- )
+ data class MyFacet(
+ val myValue: String,
+ ) : Facet
+
+ class MyTypedRelay :
+ TypedRelay by Relay.buildTypedRelay(
+ { myFacet ->
+ myFacet.myValue
+ },
+ )
}
private interface Toggles {
@@ -80,8 +97,9 @@ private interface Toggles {
}
internal fun samplePrintConfig() {
- class PropertyBehaviorChangeConfig(private val toggles: Toggles) :
- PrintRelay.Configuration by PrintRelay.Configuration.Default() {
+ class PropertyBehaviorChangeConfig(
+ private val toggles: Toggles,
+ ) : PrintRelay.Configuration by PrintRelay.Configuration.Default() {
override var detailedMode: Boolean
get() = toggles["PrintRelay Toggle"]
set(_) = Unit
diff --git a/telemetry/src/main/java/com/kroger/telemetry/StandardTelemeter.kt b/telemetry/src/main/java/com/kroger/telemetry/StandardTelemeter.kt
index 1e9b910..857146d 100644
--- a/telemetry/src/main/java/com/kroger/telemetry/StandardTelemeter.kt
+++ b/telemetry/src/main/java/com/kroger/telemetry/StandardTelemeter.kt
@@ -43,43 +43,50 @@ internal class StandardTelemeter(
private val parent: Telemeter?,
internal val flowConfig: Telemeter.EventFlowConfig,
) : Telemeter {
-
private val coroutineScope = flowConfig.scope ?: CoroutineScope(Dispatchers.Default)
- private val events = MutableSharedFlow(
- replay = flowConfig.replay,
- extraBufferCapacity = flowConfig.extraBufferCapacity,
- onBufferOverflow = flowConfig.onBufferOverflow,
- )
+ private val events =
+ MutableSharedFlow(
+ replay = flowConfig.replay,
+ extraBufferCapacity = flowConfig.extraBufferCapacity,
+ onBufferOverflow = flowConfig.onBufferOverflow,
+ )
init {
relays.forEach { relay ->
- events.onEach { event ->
- Result.runCatching {
- relay.process(event)
- }.onFailure {
- val message = "An error was caught during Relay processing. It was $it"
- val facet = Failure(message = message, throwable = it)
- // Avoid loops
- if (event.facets.contains(facet)) return@onEach
- val failureEvent = object : Event {
- override val description: String = message
- override val facets: List = listOf(facet)
- }
- record(failureEvent)
- }
- }.launchIn(coroutineScope)
+ events
+ .onEach { event ->
+ Result
+ .runCatching {
+ relay.process(event)
+ }.onFailure {
+ val message = "An error was caught during Relay processing. It was $it"
+ val facet = Failure(message = message, throwable = it)
+ // Avoid loops
+ if (event.facets.contains(facet)) return@onEach
+ val failureEvent =
+ object : Event {
+ override val description: String = message
+ override val facets: List = listOf(facet)
+ }
+ record(failureEvent)
+ }
+ }.launchIn(coroutineScope)
}
}
- override fun record(event: Event, withFacets: List?) {
+ override fun record(
+ event: Event,
+ withFacets: List?,
+ ) {
// Note that this composition of facets into an anonymous object erases the original
// type of the event. This means that any type checking in relays should depend on facets.
val allFacets = (resolveFacets(event.facets) + (withFacets ?: listOf())).addMetaFacets()
- val additionallyFacetedEvent = object : Event {
- override val description = event.description
- override val facets = allFacets
- }
+ val additionallyFacetedEvent =
+ object : Event {
+ override val description = event.description
+ override val facets = allFacets
+ }
coroutineScope.launch {
events.emit(additionallyFacetedEvent)
@@ -88,24 +95,26 @@ internal class StandardTelemeter(
parent?.record(additionallyFacetedEvent)
}
- private fun resolveFacets(facets: List): List = if (facetResolvers.isNotEmpty()) {
- val unresolvedFacets: List = facets.filterIsInstance()
- val resolvedFacets: List = facets.filterNot { it is UnresolvedFacet }
+ private fun resolveFacets(facets: List): List =
+ if (facetResolvers.isNotEmpty()) {
+ val unresolvedFacets: List = facets.filterIsInstance()
+ val resolvedFacets: List = facets.filterNot { it is UnresolvedFacet }
- val finalFacets: List = unresolvedFacets.flatMap { unresolvedFacet ->
- try {
- facetResolvers[unresolvedFacet::class.java]?.resolve(unresolvedFacet)
- ?: listOf(unresolvedFacet)
- } catch (e: Exception) {
- // We must swallow this error to continue processing the rest of the facets, and continue on to the relays
- listOf(unresolvedFacet)
- }
- } + resolvedFacets
+ val finalFacets: List =
+ unresolvedFacets.flatMap { unresolvedFacet ->
+ try {
+ facetResolvers[unresolvedFacet::class.java]?.resolve(unresolvedFacet)
+ ?: listOf(unresolvedFacet)
+ } catch (e: Exception) {
+ // We must swallow this error to continue processing the rest of the facets, and continue on to the relays
+ listOf(unresolvedFacet)
+ }
+ } + resolvedFacets
- finalFacets
- } else {
- facets
- }
+ finalFacets
+ } else {
+ facets
+ }
private fun List.addMetaFacets(): List {
// Only a leaf node Telemeter needs to propagate ThreadData to a Relay, so check if
@@ -115,7 +124,9 @@ internal class StandardTelemeter(
listOf(
Thread.currentThread().let { ThreadData(it.name, it.stackTrace) },
)
- } else listOf()
+ } else {
+ listOf()
+ }
/* telemeter facets start the list so that as we move back upwards through the
telemeter chain events get automatic scoping, for example:
grandChildFacets + ...
@@ -123,7 +134,7 @@ internal class StandardTelemeter(
parentFacets + (childFacets + (grandChildFacets + ...))
so they could be something like:
listOf(Prefix.App + (Prefix.Module + (Prefix.Class)))
- */
+ */
return facets + threadFacet + this
}
}
diff --git a/telemetry/src/main/java/com/kroger/telemetry/Telemeter.kt b/telemetry/src/main/java/com/kroger/telemetry/Telemeter.kt
index 9ff9691..6118b3c 100644
--- a/telemetry/src/main/java/com/kroger/telemetry/Telemeter.kt
+++ b/telemetry/src/main/java/com/kroger/telemetry/Telemeter.kt
@@ -54,7 +54,10 @@ public interface Telemeter {
* type of an Event will be overwritten when recorded, so type-checks on Events should be
* avoided. Instead, type-checks should be used on [Facet]s.
*/
- public fun record(event: Event, withFacets: List? = null)
+ public fun record(
+ event: Event,
+ withFacets: List? = null,
+ )
/**
* Used to configure the event flow that propagates events to relays.
@@ -95,35 +98,36 @@ public interface Telemeter {
facets: List = listOf(),
facetResolvers: Map, FacetResolver> = mapOf(),
flowConfig: EventFlowConfig = defaultTelemetryFlowConfig,
- ): Telemeter {
- return StandardTelemeter(
+ ): Telemeter =
+ StandardTelemeter(
relays = relays,
facetResolvers = facetResolvers,
facets = facets,
parent = null,
flowConfig = flowConfig,
)
- }
/**
* Default event flow configuration for Telemetry, to ensure event processing is not
* blocked by slowest relay.
*/
- public val defaultTelemetryFlowConfig: EventFlowConfig = EventFlowConfig(
- replay = 64,
- extraBufferCapacity = 64,
- onBufferOverflow = BufferOverflow.DROP_OLDEST,
- )
+ public val defaultTelemetryFlowConfig: EventFlowConfig =
+ EventFlowConfig(
+ replay = 64,
+ extraBufferCapacity = 64,
+ onBufferOverflow = BufferOverflow.DROP_OLDEST,
+ )
/**
* Default event flow configuration used by the coroutine standard library, which
* will suspend new events until the slowest relay has finished processed the last event.
*/
- public val defaultSharedFlowConfig: EventFlowConfig = EventFlowConfig(
- replay = 0,
- extraBufferCapacity = 0,
- onBufferOverflow = BufferOverflow.SUSPEND,
- )
+ public val defaultSharedFlowConfig: EventFlowConfig =
+ EventFlowConfig(
+ replay = 0,
+ extraBufferCapacity = 0,
+ onBufferOverflow = BufferOverflow.SUSPEND,
+ )
}
}
@@ -139,10 +143,11 @@ public fun Telemeter.child(
relays: List = listOf(),
facets: List = listOf(),
facetResolvers: Map, FacetResolver> = mapOf(),
-): Telemeter = StandardTelemeter(
- relays = relays,
- facets = facets,
- parent = this,
- flowConfig = (this as? StandardTelemeter)?.flowConfig ?: Telemeter.defaultTelemetryFlowConfig,
- facetResolvers = facetResolvers,
-)
+): Telemeter =
+ StandardTelemeter(
+ relays = relays,
+ facets = facets,
+ parent = this,
+ flowConfig = (this as? StandardTelemeter)?.flowConfig ?: Telemeter.defaultTelemetryFlowConfig,
+ facetResolvers = facetResolvers,
+ )
diff --git a/telemetry/src/main/java/com/kroger/telemetry/facet/DeveloperMetricsFacet.kt b/telemetry/src/main/java/com/kroger/telemetry/facet/DeveloperMetricsFacet.kt
index 93303c8..2a6622c 100644
--- a/telemetry/src/main/java/com/kroger/telemetry/facet/DeveloperMetricsFacet.kt
+++ b/telemetry/src/main/java/com/kroger/telemetry/facet/DeveloperMetricsFacet.kt
@@ -40,7 +40,9 @@ public interface DeveloperMetricsFacet : Facet.Computed