Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ android {
buildConfigField("String", "NAVER_CLIENT_SECRET", properties["NAVER_CLIENT_SECRET"].toString())
buildConfigField("String", "KAKAO_NATIVE_APP_KEY", properties["kakao.native.app.key"].toString())
manifestPlaceholders["KAKAO_NATIVE_APP_KEY_MANIFEST"] = properties["kakao.native.app.key.manifest"].toString()
buildConfigField("String", "DISCORD_WEBHOOK_URL", properties["DISCORD_WEBHOOK_URL"].toString())
}

signingConfigs {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.kuit.findu.data.dataremote.service

import com.kuit.findu.domain.model.DiscordLogBody
import retrofit2.http.Body
import retrofit2.http.POST
import retrofit2.http.Url

interface WebhookService {
@POST
suspend fun sendLog(
@Url webhookUrl: String,
@Body body: DiscordLogBody
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.kuit.findu.data.dataremote.util

import com.kuit.findu.data.dataremote.service.WebhookService
import com.kuit.findu.domain.model.DiscordLogBody
import com.kuit.findu.domain.repository.UserInfoRepository
import javax.inject.Inject

class DiscordLogger @Inject constructor(
private val webhookService: WebhookService,
private val userInfoRepository: UserInfoRepository,
private val webhookUrl: String,
) {

suspend fun logServerError(
code: Int,
method: String,
url: String,
) {
val deviceId = userInfoRepository.getDeviceId()
val nickname = userInfoRepository.getNickname()

val body = DiscordLogBody(
content = """
🚨 **Server Error 발생**

👤 User
- Nickname: $nickname
- DeviceId: $deviceId

🌐 Request
- Method: $method
- Url: $url
- Code: $code
""".trimIndent()
)

runCatching {
webhookService.sendLog(webhookUrl, body)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,54 @@ package com.kuit.findu.data.dataremote.util

import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.crashlytics.recordException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.Interceptor
import okhttp3.Response
import javax.inject.Inject

class ErrorTrackingInterceptor @Inject constructor(
private val firebaseCrashlytics: FirebaseCrashlytics,
private val discordLogger: DiscordLogger,
) : Interceptor {

override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val response: Response

try {
response = chain.proceed(request)
} catch (e: Exception) {
// 1. 네트워크 자체가 끊긴 경우 등 (IOException)
firebaseCrashlytics.recordException(e)
throw e
}

// 2. 서버에서 응답은 왔으나 4xx, 5xx 에러인 경우
if (!response.isSuccessful) {
val code = response.code

val url = request.url.toString()

// Crashlytics에 상세 정보 기록
val exceptionMessage = when (response.code) {
in (400..499) -> "Client $code Error"
in (500..599) -> "Server $code Error"
val exceptionMessage = when (code) {
in 400..499 -> "Client $code Error"
in 500..599 -> "Server $code Error"
else -> "Unknown $code Error"
}

firebaseCrashlytics.recordException(Exception(exceptionMessage)) {
key("api_method", request.method)
key("api_url", url)
key("api_status", code)
}

if (code in 500..599) {
CoroutineScope(Dispatchers.IO).launch {
discordLogger.logServerError(
code = code,
method = request.method,
url = url
)
}
}
}

return response
Expand Down
27 changes: 27 additions & 0 deletions app/src/main/java/com/kuit/findu/di/LogModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.kuit.findu.di

import com.kuit.findu.BuildConfig
import com.kuit.findu.data.dataremote.service.WebhookService
import com.kuit.findu.data.dataremote.util.DiscordLogger
import com.kuit.findu.domain.repository.UserInfoRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object LogModule {
@Provides
@Singleton
fun provideDiscordLogger(
webhookService: WebhookService,
userInfoRepository: UserInfoRepository,
): DiscordLogger =
DiscordLogger(
webhookService,
userInfoRepository,
BuildConfig.DISCORD_WEBHOOK_URL,
)
}
42 changes: 42 additions & 0 deletions app/src/main/java/com/kuit/findu/di/LogNetworkModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.kuit.findu.di

import com.kuit.findu.data.dataremote.service.WebhookService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import jakarta.inject.Named
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object LogNetworkModule {

@Provides
@Singleton
@Named("webhook")
fun provideWebhookOkHttpClient(): OkHttpClient =
OkHttpClient.Builder().build()

@Provides
@Singleton
@Named("webhook")
fun provideWebhookRetrofit(
@Named("webhook") okHttpClient: OkHttpClient
): Retrofit =
Retrofit.Builder()
.baseUrl("https://discord.com/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()

@Provides
@Singleton
fun provideWebhookService(
@Named("webhook") retrofit: Retrofit
): WebhookService =
retrofit.create(WebhookService::class.java)
}
7 changes: 6 additions & 1 deletion app/src/main/java/com/kuit/findu/di/NetworkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.kuit.findu.BuildConfig.DEBUG
import com.kuit.findu.data.datalocal.datasource.TokenLocalDataSource
import com.kuit.findu.data.dataremote.util.AuthAuthenticator
import com.kuit.findu.data.dataremote.util.AuthInterceptor
import com.kuit.findu.data.dataremote.util.DiscordLogger
import com.kuit.findu.data.dataremote.util.ErrorTrackingInterceptor
import dagger.Module
import dagger.Provides
Expand Down Expand Up @@ -85,8 +86,12 @@ object NetworkModule {
@Singleton
fun provideErrorTrackingInterceptor(
firebaseCrashlytics: FirebaseCrashlytics,
discordLogger: DiscordLogger
): ErrorTrackingInterceptor {
return ErrorTrackingInterceptor(firebaseCrashlytics)
return ErrorTrackingInterceptor(
firebaseCrashlytics= firebaseCrashlytics,
discordLogger = discordLogger
)
}

@ExperimentalSerializationApi
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.kuit.findu.domain.model

data class DiscordLogBody(
val content: String
)