diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6af02ee7..28651f61 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -10,6 +10,7 @@ plugins { alias(libs.plugins.navigationSafeArgs) alias(libs.plugins.googleServices) alias(libs.plugins.firebaseCrashlytics) + alias(libs.plugins.firebasePerf) } val properties = Properties().apply { @@ -24,8 +25,8 @@ android { applicationId = "com.kuit.findu" minSdk = 28 targetSdk = 35 - versionCode = 19 - versionName = "1.1.4" + versionCode = 21 + versionName = "1.1.6" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" buildConfigField("String", "GPT_KEY", properties["GPT_KEY"].toString()) @@ -171,6 +172,7 @@ dependencies { implementation(libs.firebase.analytics.ktx) implementation(libs.firebase.config.ktx) implementation(libs.firebase.crashlytics) + implementation(libs.firebase.perf) // AdMob implementation("com.google.android.gms:play-services-ads:23.1.0") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7979c5fa..651a7f66 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,7 +11,8 @@ - @@ -47,6 +48,11 @@ android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-7675272869453438~5374193050" /> + + + + val duration = SystemClock.elapsedRealtime() - startTime + Log.d("ImagePerf", "보호동물 이미지 로딩 완료: ${duration}ms | ${animal.thumbnailImageUrl}") + trace.stop() + }, + onError = { _, _ -> + val duration = SystemClock.elapsedRealtime() - startTime + Log.e("ImagePerf", "보호동물 이미지 로딩 실패: ${duration}ms | ${animal.thumbnailImageUrl}") + trace.putAttribute("status", "error") + trace.stop() + } + ) + .build() + } AsyncImage( - model = animal.thumbnailImageUrl, + model = imageRequest, contentDescription = "Animal Image", contentScale = ContentScale.Crop, modifier = Modifier diff --git a/app/src/main/java/com/kuit/findu/presentation/ui/home/component/HomeReportedAnimalCard.kt b/app/src/main/java/com/kuit/findu/presentation/ui/home/component/HomeReportedAnimalCard.kt index 0c2d009f..55e00bb3 100644 --- a/app/src/main/java/com/kuit/findu/presentation/ui/home/component/HomeReportedAnimalCard.kt +++ b/app/src/main/java/com/kuit/findu/presentation/ui/home/component/HomeReportedAnimalCard.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -20,8 +21,13 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import android.os.SystemClock +import android.util.Log import coil.compose.AsyncImage +import coil.request.ImageRequest +import com.google.firebase.perf.FirebasePerformance import com.kuit.findu.R import com.kuit.findu.domain.model.ReportAnimal import com.kuit.findu.presentation.type.AnimalStateType @@ -43,8 +49,33 @@ fun HomeReportedAnimalCard( .background(shape = RoundedCornerShape(10.dp), color = FindUTheme.colors.white) .noRippleClickable { navigateToReportDetail(animal) } ) { + val context = LocalContext.current + val imageRequest = remember(animal.thumbnailImageUrl) { + val trace = FirebasePerformance.getInstance().newTrace("home_report_image_load") + var startTime = 0L + ImageRequest.Builder(context) + .data(animal.thumbnailImageUrl) + .listener( + onStart = { + startTime = SystemClock.elapsedRealtime() + trace.start() + }, + onSuccess = { _, _ -> + val duration = SystemClock.elapsedRealtime() - startTime + Log.d("ImagePerf", "제보동물 이미지 로딩 완료: ${duration}ms | ${animal.thumbnailImageUrl}") + trace.stop() + }, + onError = { _, _ -> + val duration = SystemClock.elapsedRealtime() - startTime + Log.e("ImagePerf", "제보동물 이미지 로딩 실패: ${duration}ms | ${animal.thumbnailImageUrl}") + trace.putAttribute("status", "error") + trace.stop() + } + ) + .build() + } AsyncImage( - model = animal.thumbnailImageUrl, + model = imageRequest, contentDescription = "Animal Image", contentScale = ContentScale.Crop, modifier = Modifier diff --git a/app/src/main/java/com/kuit/findu/presentation/ui/home/viewmodel/HomeViewModel.kt b/app/src/main/java/com/kuit/findu/presentation/ui/home/viewmodel/HomeViewModel.kt index c4cda3eb..8c47a961 100644 --- a/app/src/main/java/com/kuit/findu/presentation/ui/home/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/kuit/findu/presentation/ui/home/viewmodel/HomeViewModel.kt @@ -14,6 +14,7 @@ import com.kuit.findu.presentation.type.HomeReportDurationType import com.kuit.findu.presentation.type.HomeUserStatusType import com.kuit.findu.presentation.type.view.LoadState import com.kuit.findu.presentation.util.Nickname.GUEST_NAME +import com.google.firebase.perf.FirebasePerformance import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.MutableStateFlow @@ -137,8 +138,14 @@ class HomeViewModel @Inject constructor( private fun loadHomeData() { viewModelScope.launch { _uiState.update { it.copy(loadState = LoadState.Loading) } + val trace = FirebasePerformance.getInstance().newTrace("home_data_load") + trace.start() homeUseCase().fold( onSuccess = { data -> + trace.putAttribute("status", "success") + trace.putMetric("protect_animal_count", data.protectAnimalCards.size.toLong()) + trace.putMetric("report_animal_count", data.reportAnimalCards.size.toLong()) + trace.stop() _uiState.update { it.copy( loadState = LoadState.Success, @@ -148,6 +155,8 @@ class HomeViewModel @Inject constructor( } }, onFailure = { error -> + trace.putAttribute("status", "failure") + trace.stop() Log.e("HomeViewModel", "loadHomeData: $error") if(error.message?.contains("401") == true) { _uiEffect.send(HomeUiEffect.NavigateToLogin) diff --git a/build.gradle.kts b/build.gradle.kts index ebcb5dfd..ff38d455 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,4 +6,5 @@ plugins { alias(libs.plugins.navigationSafeArgs) apply false alias(libs.plugins.googleServices) apply false alias(libs.plugins.firebaseCrashlytics) apply false + alias(libs.plugins.firebasePerf) apply false } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0e29bbf2..b8333821 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,6 +5,7 @@ coilCompose = "2.5.0" composeBom = "2024.04.01" firebaseBom = "34.6.0" firebaseCrashlytics = "3.0.6" +firebasePerf = "2.0.2" googleServices = "4.4.2" kotlin = "2.0.21" coreKtx = "1.15.0" @@ -54,6 +55,7 @@ firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "fir firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics" } firebase-config-ktx = { module = "com.google.firebase:firebase-config" } firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics"} +firebase-perf = { module = "com.google.firebase:firebase-perf" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } @@ -105,6 +107,7 @@ dagger-hilt = { id = "com.google.dagger.hilt.android", version.ref = "daggerHilt navigationSafeArgs = { id = "androidx.navigation.safeargs.kotlin", version.ref = "navigationFragmentKtx" } googleServices = { id = "com.google.gms.google-services", version.ref = "googleServices" } firebaseCrashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlytics" } +firebasePerf = { id = "com.google.firebase.firebase-perf", version.ref = "firebasePerf" } [bundles] hilt = [