Skip to content

Commit 0b179ef

Browse files
authored
Merge pull request #112 from FindYou-Kuit/feat/discord-notification
[feat] #111 디스코드 에러 알림 연동
2 parents 2ecb5b2 + 18182d5 commit 0b179ef

8 files changed

Lines changed: 155 additions & 8 deletions

File tree

app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ android {
3535
buildConfigField("String", "NAVER_CLIENT_SECRET", properties["NAVER_CLIENT_SECRET"].toString())
3636
buildConfigField("String", "KAKAO_NATIVE_APP_KEY", properties["kakao.native.app.key"].toString())
3737
manifestPlaceholders["KAKAO_NATIVE_APP_KEY_MANIFEST"] = properties["kakao.native.app.key.manifest"].toString()
38+
buildConfigField("String", "DISCORD_WEBHOOK_URL", properties["DISCORD_WEBHOOK_URL"].toString())
3839
}
3940

4041
signingConfigs {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.kuit.findu.data.dataremote.service
2+
3+
import com.kuit.findu.domain.model.DiscordLogBody
4+
import retrofit2.http.Body
5+
import retrofit2.http.POST
6+
import retrofit2.http.Url
7+
8+
interface WebhookService {
9+
@POST
10+
suspend fun sendLog(
11+
@Url webhookUrl: String,
12+
@Body body: DiscordLogBody
13+
)
14+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.kuit.findu.data.dataremote.util
2+
3+
import com.kuit.findu.data.dataremote.service.WebhookService
4+
import com.kuit.findu.domain.model.DiscordLogBody
5+
import com.kuit.findu.domain.repository.UserInfoRepository
6+
import javax.inject.Inject
7+
8+
class DiscordLogger @Inject constructor(
9+
private val webhookService: WebhookService,
10+
private val userInfoRepository: UserInfoRepository,
11+
private val webhookUrl: String,
12+
) {
13+
14+
suspend fun logServerError(
15+
code: Int,
16+
method: String,
17+
url: String,
18+
) {
19+
val deviceId = userInfoRepository.getDeviceId()
20+
val nickname = userInfoRepository.getNickname()
21+
22+
val body = DiscordLogBody(
23+
content = """
24+
🚨 **Server Error 발생**
25+
26+
👤 User
27+
- Nickname: $nickname
28+
- DeviceId: $deviceId
29+
30+
🌐 Request
31+
- Method: $method
32+
- Url: $url
33+
- Code: $code
34+
""".trimIndent()
35+
)
36+
37+
runCatching {
38+
webhookService.sendLog(webhookUrl, body)
39+
}
40+
}
41+
}

app/src/main/java/com/kuit/findu/data/dataremote/util/ErrorTrackingInterceptor.kt

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,54 @@ package com.kuit.findu.data.dataremote.util
22

33
import com.google.firebase.crashlytics.FirebaseCrashlytics
44
import com.google.firebase.crashlytics.recordException
5+
import kotlinx.coroutines.CoroutineScope
6+
import kotlinx.coroutines.Dispatchers
7+
import kotlinx.coroutines.launch
58
import okhttp3.Interceptor
69
import okhttp3.Response
710
import javax.inject.Inject
811

912
class ErrorTrackingInterceptor @Inject constructor(
1013
private val firebaseCrashlytics: FirebaseCrashlytics,
14+
private val discordLogger: DiscordLogger,
1115
) : Interceptor {
16+
1217
override fun intercept(chain: Interceptor.Chain): Response {
1318
val request = chain.request()
1419
val response: Response
1520

1621
try {
1722
response = chain.proceed(request)
1823
} catch (e: Exception) {
19-
// 1. 네트워크 자체가 끊긴 경우 등 (IOException)
2024
firebaseCrashlytics.recordException(e)
2125
throw e
2226
}
2327

24-
// 2. 서버에서 응답은 왔으나 4xx, 5xx 에러인 경우
2528
if (!response.isSuccessful) {
2629
val code = response.code
27-
2830
val url = request.url.toString()
2931

30-
// Crashlytics에 상세 정보 기록
31-
val exceptionMessage = when (response.code) {
32-
in (400..499) -> "Client $code Error"
33-
in (500..599) -> "Server $code Error"
32+
val exceptionMessage = when (code) {
33+
in 400..499 -> "Client $code Error"
34+
in 500..599 -> "Server $code Error"
3435
else -> "Unknown $code Error"
3536
}
37+
3638
firebaseCrashlytics.recordException(Exception(exceptionMessage)) {
3739
key("api_method", request.method)
3840
key("api_url", url)
3941
key("api_status", code)
4042
}
43+
44+
if (code in 500..599) {
45+
CoroutineScope(Dispatchers.IO).launch {
46+
discordLogger.logServerError(
47+
code = code,
48+
method = request.method,
49+
url = url
50+
)
51+
}
52+
}
4153
}
4254

4355
return response
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.kuit.findu.di
2+
3+
import com.kuit.findu.BuildConfig
4+
import com.kuit.findu.data.dataremote.service.WebhookService
5+
import com.kuit.findu.data.dataremote.util.DiscordLogger
6+
import com.kuit.findu.domain.repository.UserInfoRepository
7+
import dagger.Module
8+
import dagger.Provides
9+
import dagger.hilt.InstallIn
10+
import dagger.hilt.components.SingletonComponent
11+
import javax.inject.Singleton
12+
13+
@Module
14+
@InstallIn(SingletonComponent::class)
15+
object LogModule {
16+
@Provides
17+
@Singleton
18+
fun provideDiscordLogger(
19+
webhookService: WebhookService,
20+
userInfoRepository: UserInfoRepository,
21+
): DiscordLogger =
22+
DiscordLogger(
23+
webhookService,
24+
userInfoRepository,
25+
BuildConfig.DISCORD_WEBHOOK_URL,
26+
)
27+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.kuit.findu.di
2+
3+
import com.kuit.findu.data.dataremote.service.WebhookService
4+
import dagger.Module
5+
import dagger.Provides
6+
import dagger.hilt.InstallIn
7+
import dagger.hilt.components.SingletonComponent
8+
import okhttp3.OkHttpClient
9+
import retrofit2.Retrofit
10+
import retrofit2.converter.gson.GsonConverterFactory
11+
import javax.inject.Named
12+
import javax.inject.Singleton
13+
14+
@Module
15+
@InstallIn(SingletonComponent::class)
16+
object LogNetworkModule {
17+
18+
@Provides
19+
@Singleton
20+
@Named("webhook")
21+
fun provideWebhookOkHttpClient(): OkHttpClient =
22+
OkHttpClient.Builder().build()
23+
24+
@Provides
25+
@Singleton
26+
@Named("webhook")
27+
fun provideWebhookRetrofit(
28+
@Named("webhook") okHttpClient: OkHttpClient
29+
): Retrofit =
30+
Retrofit.Builder()
31+
.baseUrl("https://discord.com/")
32+
.client(okHttpClient)
33+
.addConverterFactory(GsonConverterFactory.create())
34+
.build()
35+
36+
@Provides
37+
@Singleton
38+
fun provideWebhookService(
39+
@Named("webhook") retrofit: Retrofit
40+
): WebhookService =
41+
retrofit.create(WebhookService::class.java)
42+
}

app/src/main/java/com/kuit/findu/di/NetworkModule.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.kuit.findu.BuildConfig.DEBUG
88
import com.kuit.findu.data.datalocal.datasource.TokenLocalDataSource
99
import com.kuit.findu.data.dataremote.util.AuthAuthenticator
1010
import com.kuit.findu.data.dataremote.util.AuthInterceptor
11+
import com.kuit.findu.data.dataremote.util.DiscordLogger
1112
import com.kuit.findu.data.dataremote.util.ErrorTrackingInterceptor
1213
import dagger.Module
1314
import dagger.Provides
@@ -85,8 +86,12 @@ object NetworkModule {
8586
@Singleton
8687
fun provideErrorTrackingInterceptor(
8788
firebaseCrashlytics: FirebaseCrashlytics,
89+
discordLogger: DiscordLogger
8890
): ErrorTrackingInterceptor {
89-
return ErrorTrackingInterceptor(firebaseCrashlytics)
91+
return ErrorTrackingInterceptor(
92+
firebaseCrashlytics= firebaseCrashlytics,
93+
discordLogger = discordLogger
94+
)
9095
}
9196

9297
@ExperimentalSerializationApi
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.kuit.findu.domain.model
2+
3+
data class DiscordLogBody(
4+
val content: String
5+
)

0 commit comments

Comments
 (0)