mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat(analytics): Integrate _more_ Datadog (#2633)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
parent
cde871de91
commit
23c87fb48c
9 changed files with 60 additions and 22 deletions
8
.github/workflows/pull-request.yml
vendored
8
.github/workflows/pull-request.yml
vendored
|
|
@ -12,14 +12,6 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test_secrets:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_SECRET: ${{ secrets.TEST_SECRET }}
|
||||
steps:
|
||||
- name: Test Secrets
|
||||
run: |
|
||||
echo "$TEST_SECRET"
|
||||
|
||||
build_and_detekt:
|
||||
if: github.repository == 'meshtastic/Meshtastic-Android' && github.head_ref != 'scheduled-updates'
|
||||
|
|
|
|||
6
.github/workflows/reusable-android-build.yml
vendored
6
.github/workflows/reusable-android-build.yml
vendored
|
|
@ -9,8 +9,6 @@ on:
|
|||
required: false
|
||||
DATADOG_CLIENT_TOKEN:
|
||||
required: false
|
||||
TEST_SECRET:
|
||||
required: false
|
||||
inputs:
|
||||
upload_artifacts:
|
||||
description: 'Whether to upload build and Detekt artifacts'
|
||||
|
|
@ -27,10 +25,6 @@ jobs:
|
|||
DATADOG_CLIENT_TOKEN: ${{ secrets.DATADOG_CLIENT_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Test Secrets
|
||||
env:
|
||||
TEST_SECRET: ${{ secrets.TEST_SECRET }}
|
||||
run: echo "$TEST_SECRET"
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ android {
|
|||
}
|
||||
}
|
||||
buildTypes {
|
||||
named("release") {
|
||||
release {
|
||||
if (keystoreProperties["storeFile"] != null) {
|
||||
signingConfig = signingConfigs.named("release").get()
|
||||
}
|
||||
|
|
@ -134,7 +134,10 @@ android {
|
|||
isShrinkResources = true
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
}
|
||||
named("debug") { isPseudoLocalesEnabled = true }
|
||||
debug {
|
||||
isDebuggable = true
|
||||
isPseudoLocalesEnabled = true
|
||||
}
|
||||
}
|
||||
bundle { language { enableSplit = false } }
|
||||
buildFeatures {
|
||||
|
|
|
|||
|
|
@ -22,10 +22,14 @@ import android.content.Context
|
|||
import android.content.SharedPreferences
|
||||
import android.provider.Settings
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.core.content.edit
|
||||
import androidx.navigation.NavHostController
|
||||
import com.geeksville.mesh.BuildConfig
|
||||
import com.geeksville.mesh.analytics.AnalyticsProvider
|
||||
import com.geeksville.mesh.analytics.NopAnalytics
|
||||
import com.geeksville.mesh.android.BuildUtils.debug
|
||||
import com.geeksville.mesh.android.BuildUtils.info
|
||||
import com.geeksville.mesh.model.DeviceHardware
|
||||
import timber.log.Timber
|
||||
|
||||
|
|
@ -80,4 +84,13 @@ val Context.isGooglePlayAvailable: Boolean
|
|||
@Suppress("UnusedParameter")
|
||||
fun setAttributes(deviceVersion: String, deviceHardware: DeviceHardware) {
|
||||
// No-op for F-Droid version
|
||||
info("Setting attributes: deviceVersion=$deviceVersion, deviceHardware=$deviceHardware")
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AddNavigationTracking(navController: NavHostController) {
|
||||
// No-op for F-Droid version
|
||||
navController.addOnDestinationChangedListener { _, destination, _ ->
|
||||
debug("Navigation changed to: ${destination.route}")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,11 +21,14 @@ import android.app.Application
|
|||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.core.content.edit
|
||||
import androidx.navigation.NavHostController
|
||||
import com.datadog.android.Datadog
|
||||
import com.datadog.android.DatadogSite
|
||||
import com.datadog.android.compose.ExperimentalTrackingApi
|
||||
import com.datadog.android.compose.NavigationViewTrackingEffect
|
||||
import com.datadog.android.compose.enableComposeActionTracking
|
||||
import com.datadog.android.core.configuration.Configuration
|
||||
import com.datadog.android.log.Logger
|
||||
|
|
@ -35,7 +38,11 @@ import com.datadog.android.privacy.TrackingConsent
|
|||
import com.datadog.android.rum.GlobalRumMonitor
|
||||
import com.datadog.android.rum.Rum
|
||||
import com.datadog.android.rum.RumConfiguration
|
||||
import com.datadog.android.rum.tracking.AcceptAllNavDestinations
|
||||
import com.datadog.android.timber.DatadogTree
|
||||
import com.datadog.android.trace.AndroidTracer
|
||||
import com.datadog.android.trace.Trace
|
||||
import com.datadog.android.trace.TraceConfiguration
|
||||
import com.geeksville.mesh.BuildConfig
|
||||
import com.geeksville.mesh.analytics.AnalyticsProvider
|
||||
import com.geeksville.mesh.analytics.FirebaseAnalytics
|
||||
|
|
@ -44,6 +51,7 @@ import com.geeksville.mesh.util.exceptionReporter
|
|||
import com.google.android.gms.common.ConnectionResult
|
||||
import com.google.android.gms.common.GoogleApiAvailabilityLight
|
||||
import com.suddenh4x.ratingdialog.AppRating
|
||||
import io.opentracing.util.GlobalTracer
|
||||
import timber.log.Timber
|
||||
|
||||
/** Created by kevinh on 1/4/15. */
|
||||
|
|
@ -135,10 +143,9 @@ open class GeeksvilleApplication :
|
|||
val logger =
|
||||
Logger.Builder()
|
||||
.setNetworkInfoEnabled(true)
|
||||
.setLogcatLogsEnabled(true)
|
||||
.setRemoteSampleRate(sampleRate)
|
||||
.setBundleWithTraceEnabled(true)
|
||||
.setName("TimberLogger")
|
||||
.setBundleWithRumEnabled(true)
|
||||
.build()
|
||||
val configuration =
|
||||
Configuration.Builder(
|
||||
|
|
@ -157,7 +164,6 @@ open class GeeksvilleApplication :
|
|||
TrackingConsent.NOT_GRANTED
|
||||
}
|
||||
Datadog.initialize(this, configuration, consent)
|
||||
Datadog.setVerbosity(Log.VERBOSE)
|
||||
|
||||
val rumConfiguration =
|
||||
RumConfiguration.Builder(BuildConfig.datadogApplicationId)
|
||||
|
|
@ -166,7 +172,9 @@ open class GeeksvilleApplication :
|
|||
.trackFrustrations(true)
|
||||
.trackLongTasks()
|
||||
.trackNonFatalAnrs(true)
|
||||
.trackUserInteractions()
|
||||
// Re-enable tracking when auto instrumentation available. See note in `app/build.gradle`
|
||||
.disableUserInteractionTracking()
|
||||
// .trackUserInteractions()
|
||||
.enableComposeActionTracking()
|
||||
.build()
|
||||
Rum.enable(rumConfiguration)
|
||||
|
|
@ -174,6 +182,12 @@ open class GeeksvilleApplication :
|
|||
val logsConfig = LogsConfiguration.Builder().build()
|
||||
Logs.enable(logsConfig)
|
||||
|
||||
val traceConfig = TraceConfiguration.Builder().build()
|
||||
Trace.enable(traceConfig)
|
||||
|
||||
val tracer = AndroidTracer.Builder().build()
|
||||
GlobalTracer.registerIfAbsent(tracer)
|
||||
|
||||
Timber.plant(Timber.DebugTree(), DatadogTree(logger))
|
||||
}
|
||||
}
|
||||
|
|
@ -188,3 +202,13 @@ val Context.isGooglePlayAvailable: Boolean
|
|||
GoogleApiAvailabilityLight.getInstance().isGooglePlayServicesAvailable(this).let {
|
||||
it != ConnectionResult.SERVICE_MISSING && it != ConnectionResult.SERVICE_INVALID
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTrackingApi::class)
|
||||
@Composable
|
||||
fun AddNavigationTracking(navController: NavHostController) {
|
||||
NavigationViewTrackingEffect(
|
||||
navController = navController,
|
||||
trackArguments = true,
|
||||
destinationPredicate = AcceptAllNavDestinations(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ import androidx.navigation.compose.rememberNavController
|
|||
import com.geeksville.mesh.BuildConfig
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.android.AddNavigationTracking
|
||||
import com.geeksville.mesh.android.BuildUtils.debug
|
||||
import com.geeksville.mesh.android.setAttributes
|
||||
import com.geeksville.mesh.model.BluetoothViewModel
|
||||
|
|
@ -159,6 +160,8 @@ fun MainScreen(
|
|||
}
|
||||
}
|
||||
|
||||
AddNavigationTracking(navController)
|
||||
|
||||
if (connectionState.isConnected()) {
|
||||
requestChannelSet?.let { newChannelSet -> ScannedQrCodeDialog(uIViewModel, newChannelSet) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,8 +90,10 @@ datastore-preferences = { group = "androidx.datastore", name = "datastore-prefer
|
|||
dd-sdk-android-compose = { group = "com.datadoghq", name = "dd-sdk-android-compose", version.ref = "dd-sdk-android" }
|
||||
dd-sdk-android-gradle-plugin = { group = "com.datadoghq", name = "dd-sdk-android-gradle-plugin", version.ref = "dd-sdk-android-gradle-plugin" }
|
||||
dd-sdk-android-logs = { group = "com.datadoghq", name = "dd-sdk-android-logs", version.ref = "dd-sdk-android" }
|
||||
dd-sdk-android-okhttp = { group = "com.datadoghq", name = "dd-sdk-android-okhttp", version.ref = "dd-sdk-android" }
|
||||
dd-sdk-android-rum = { group = "com.datadoghq", name = "dd-sdk-android-rum", version.ref = "dd-sdk-android" }
|
||||
dd-sdk-android-timber = { group = "com.datadoghq", name = "dd-sdk-android-timber", version.ref = "dd-sdk-android" }
|
||||
dd-sdk-android-trace = { group = "com.datadoghq", name = "dd-sdk-android-trace", version.ref = "dd-sdk-android" }
|
||||
detekt-formatting = { group = "io.gitlab.arturbosch.detekt", name = "detekt-formatting", version.ref = "detekt" }
|
||||
emoji2-emojipicker = { group = "androidx.emoji2", name = "emoji2-emojipicker", version.ref = "emoji2" }
|
||||
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" }
|
||||
|
|
@ -193,7 +195,7 @@ osm = ["osmdroid-android", "osmbonuspack", "mgrs"]
|
|||
firebase = ["firebase-analytics", "firebase-crashlytics"]
|
||||
|
||||
# Datadog
|
||||
datadog = ["dd-sdk-android-compose", "dd-sdk-android-logs", "dd-sdk-android-timber", "dd-sdk-android-rum"]
|
||||
datadog = ["dd-sdk-android-compose", "dd-sdk-android-logs", "dd-sdk-android-okhttp", "dd-sdk-android-rum", "dd-sdk-android-timber", "dd-sdk-android-trace"]
|
||||
|
||||
# Protobuf
|
||||
protobuf = ["protobuf-kotlin"]
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ dependencies {
|
|||
implementation(libs.bundles.hilt)
|
||||
implementation(libs.bundles.retrofit)
|
||||
implementation(libs.bundles.coil)
|
||||
"googleImplementation"(libs.bundles.datadog)
|
||||
ksp(libs.hilt.compiler)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
detektPlugins(libs.detekt.formatting)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import coil3.request.crossfade
|
|||
import coil3.svg.SvgDecoder
|
||||
import coil3.util.DebugLogger
|
||||
import coil3.util.Logger
|
||||
import com.datadog.android.okhttp.DatadogEventListener
|
||||
import com.datadog.android.okhttp.DatadogInterceptor
|
||||
import com.geeksville.mesh.network.BuildConfig
|
||||
import com.geeksville.mesh.network.retrofit.ApiService
|
||||
import dagger.Module
|
||||
|
|
@ -49,13 +51,17 @@ class ApiModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideOkHttpClient(): OkHttpClient {
|
||||
|
||||
val loggingInterceptor = HttpLoggingInterceptor().apply {
|
||||
if (BuildConfig.DEBUG) {
|
||||
setLevel(HttpLoggingInterceptor.Level.BODY)
|
||||
}
|
||||
}
|
||||
val tracedHosts = listOf("meshtastic.org")
|
||||
return OkHttpClient.Builder()
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.addInterceptor(DatadogInterceptor.Builder(tracedHosts).build())
|
||||
.eventListenerFactory(DatadogEventListener.Factory())
|
||||
.build()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue