This commit is contained in:
Menci
2024-12-12 02:28:19 +08:00
parent ee88be613c
commit 5ed89754b3
7 changed files with 129 additions and 105 deletions

View File

@@ -1,15 +1,15 @@
package icu.samnyan.aqua.sega.chusan
import ext.*
import icu.samnyan.aqua.net.db.APIMetrics
import icu.samnyan.aqua.net.utils.simpleDescribe
import icu.samnyan.aqua.sega.chunithm.handler.impl.GetGameIdlistHandler
import icu.samnyan.aqua.sega.chusan.handler.*
import icu.samnyan.aqua.sega.general.BaseHandler
import icu.samnyan.aqua.spring.Metrics
import org.slf4j.LoggerFactory
import org.springframework.web.bind.annotation.*
import kotlin.reflect.full.declaredMemberProperties
/**
* @author samnyan (privateamusement@protonmail.com)
*/
@@ -71,8 +71,6 @@ class ChusanServletController(
val getUserNetBattleRankingInfo: GetUserNetBattleRankingInfoHandler,
val getGameMapAreaCondition: GetGameMapAreaConditionHandler
) {
val metrics = APIMetrics("chusan")
val logger = LoggerFactory.getLogger(ChusanServletController::class.java)
val getUserCtoCPlay = BaseHandler { """{"userId":"${it["userId"]}","orderBy":"0","count":"0","userCtoCPlayList":[]}""" }
@@ -122,16 +120,31 @@ class ChusanServletController(
}
logger.info("Chu3 $api : $request")
if (api !in noopEndpoint && !handlers.containsKey(api)) {
logger.warn("Chu3 $api not found")
return """{"returnCode":"1","apiName":"$api"}"""
}
// Only record the counter metrics if the API is known.
Metrics.counter("aquadx_chusan_api_call", "api" to api).increment()
if (api in noopEndpoint) {
return """{"returnCode":"1"}"""
}
return metrics[api] {
handlers[api]?.handle(request) ?: {
logger.warn("Chu3 $api not found")
"""{"returnCode":"1","apiName":"$api"}"""
return try {
Metrics.timer("aquadx_chusan_api_latency", "api" to api).recordCallable {
handlers[api]?.handle(request) ?: {
logger.warn("Chu3 $api not found")
"""{"returnCode":"1","apiName":"$api"}"""
}
}
} catch (e: Exception) {
Metrics.counter(
"aquadx_chusan_api_error",
"api" to api, "error" to e.simpleDescribe()
).increment()
throw e
}
}
}

View File

@@ -1,11 +1,12 @@
package icu.samnyan.aqua.sega.maimai2
import ext.*
import icu.samnyan.aqua.net.db.APIMetrics
import icu.samnyan.aqua.net.utils.ApiException
import icu.samnyan.aqua.net.utils.simpleDescribe
import icu.samnyan.aqua.sega.general.BaseHandler
import icu.samnyan.aqua.sega.maimai2.handler.*
import icu.samnyan.aqua.sega.maimai2.model.Mai2Repos
import icu.samnyan.aqua.spring.Metrics
import io.ktor.client.request.*
import org.slf4j.LoggerFactory
import org.springframework.http.ResponseEntity
@@ -41,8 +42,6 @@ class Maimai2ServletController(
private val GAME_SETTING_TIME_FMT = DateTimeFormatter.ofPattern("HH:mm:00")
}
val metrics = APIMetrics("maimai2")
val getUserExtend = UserReqHandler { _, userId -> mapOf(
"userId" to userId,
"userExtend" to (repos.userExtend.findSingleByUser_Card_ExtId(userId)() ?: (404 - "User not found"))
@@ -343,6 +342,13 @@ class Maimai2ServletController(
@API("/{api}")
fun handle(@PathVariable api: String, @RequestBody request: Map<String, Any>): Any {
logger.info("Mai2 < $api : ${request.toJson()}") // TODO: Optimize logging
if (api !in noopEndpoint && api !in staticEndpoint && !handlers.containsKey(api)) {
logger.warn("Mai2 > $api not found")
return """{"returnCode":1,"apiName":"com.sega.maimai2servlet.api.$api"}"""
}
// Only record the counter metrics if the API is known.
Metrics.counter("aquadx_maimai2_api_call", "api" to api).increment()
if (api in noopEndpoint) {
logger.info("Mai2 > $api no-op")
@@ -354,20 +360,23 @@ class Maimai2ServletController(
return staticEndpoint[api]!!
}
if (!handlers.containsKey(api)) {
logger.warn("Mai2 > $api not found")
return """{"returnCode":1,"apiName":"com.sega.maimai2servlet.api.$api"}"""
}
return try { metrics[api] {
handlers[api]!!.handle(request).let { if (it is String) it else it.toJson() }.also {
if (api !in setOf("GetUserItemApi", "GetGameEventApi"))
logger.info("Mai2 > $api : $it")
return try {
Metrics.timer("aquadx_maimai2_api_latency", "api" to api).recordCallable {
handlers[api]!!.handle(request).let { if (it is String) it else it.toJson() }.also {
if (api !in setOf("GetUserItemApi", "GetGameEventApi"))
logger.info("Mai2 > $api : $it")
}
}
} }
catch (e: ApiException) {
// It's a bad practice to return 200 ok on error, but this is what maimai does so we have to follow
return ResponseEntity.ok().body("""{"returnCode":0,"apiName":"com.sega.maimai2servlet.api.$api","message":"${e.message?.replace("\"", "\\\"")} - ${e.code}"}""")
} catch (e: Exception) {
Metrics.counter(
"aquadx_maimai2_api_error",
"api" to api, "error" to e.simpleDescribe()
).increment()
if (e is ApiException) {
// It's a bad practice to return 200 ok on error, but this is what maimai does so we have to follow
return ResponseEntity.ok().body("""{"returnCode":0,"apiName":"com.sega.maimai2servlet.api.$api","message":"${e.message?.replace("\"", "\\\"")} - ${e.code}"}""")
} else throw e
}
}
}

View File

@@ -1,8 +1,6 @@
package icu.samnyan.aqua.sega.maimai2.handler
import ext.millis
import icu.samnyan.aqua.net.db.APIMetrics
import icu.samnyan.aqua.net.db.unaryPlus
import icu.samnyan.aqua.sega.allnet.TokenChecker
import icu.samnyan.aqua.sega.general.BaseHandler
import icu.samnyan.aqua.sega.maimai2.model.Mai2UserDataRepo
@@ -10,6 +8,7 @@ import icu.samnyan.aqua.sega.maimai2.model.Mai2UserPlaylogRepo
import icu.samnyan.aqua.sega.maimai2.model.request.UploadUserPlaylog
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserPlaylog
import icu.samnyan.aqua.sega.util.jackson.BasicMapper
import icu.samnyan.aqua.spring.Metrics
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component
import kotlin.jvm.optionals.getOrNull
@@ -31,8 +30,6 @@ class UploadUserPlaylogHandler(
val VALID_GAME_IDS = setOf("SDEZ", "SDGA", "SDGB")
}
val metrics = APIMetrics("maimai2")
override fun handle(request: Map<String, Any>): String {
val req = mapper.convert(request, UploadUserPlaylog::class.java)
@@ -40,7 +37,10 @@ class UploadUserPlaylogHandler(
if (version != null) {
val session = TokenChecker.getCurrentSession()
val gameId = if (session?.gameId in VALID_GAME_IDS) session!!.gameId else ""
+metrics["game_version_count", "game_id" to gameId, "version" to version]
Metrics.counter(
"aquadx_maimai2_playlog_game_version",
"game_id" to gameId, "version" to version
).increment()
}
// Save if the user is registered

View File

@@ -1,10 +1,10 @@
package icu.samnyan.aqua.sega.wacca
import ext.*
import icu.samnyan.aqua.net.db.APIMetrics
import icu.samnyan.aqua.net.db.AquaGameOptions
import icu.samnyan.aqua.net.games.wacca.Wacca
import icu.samnyan.aqua.net.utils.ApiException
import icu.samnyan.aqua.net.utils.simpleDescribe
import icu.samnyan.aqua.sega.general.dao.CardRepository
import icu.samnyan.aqua.sega.wacca.WaccaItemType.*
import icu.samnyan.aqua.sega.wacca.WaccaItemType.NOTE_COLOR
@@ -13,6 +13,7 @@ import icu.samnyan.aqua.sega.wacca.WaccaItemType.TOUCH_EFFECT
import icu.samnyan.aqua.sega.wacca.WaccaOptionType.*
import icu.samnyan.aqua.sega.wacca.model.BaseRequest
import icu.samnyan.aqua.sega.wacca.model.db.*
import icu.samnyan.aqua.spring.Metrics
import io.ktor.client.utils.*
import jakarta.servlet.http.HttpServletRequest
import org.springframework.beans.factory.annotation.Autowired
@@ -33,8 +34,6 @@ class WaccaServer {
@Autowired lateinit var rp: WaccaRepos
@Autowired lateinit var wacca: Wacca
val metrics = APIMetrics("wacca")
val handlerMap = mutableMapOf<String, (BaseRequest, List<Any>) -> Any>()
val cacheMap = mutableMapOf<String, String>()
@@ -82,28 +81,42 @@ class WaccaServer {
/** Handle all requests */
@API("/api/**")
fun handle(req: HttpServletRequest, @RB body: String): Any {
// Normalize path
val path = req.requestURI.removePrefix("/g/wacca").removePrefix("/WaccaServlet")
.removePrefix("/api").removePrefix("/").lowercase()
if (path !in cacheMap && path !in handlerMap) {
return resp("[]", 1, "Not Found")
}
// Only record the counter metrics if the API is known.
Metrics.counter("aquadx_wacca_api_call", "api" to path).increment()
if (path in cacheMap) return resp(cacheMap[path]!!)
else if (path !in handlerMap) return resp("[]", 1, "Not Found")
log.info("Wacca < $path : $body")
return try { metrics[path] {
val br = JACKSON.parse<BaseRequest>(body)
handlerMap[path]!!(br, br.params).let { when (it) {
is String -> resp(it)
is List<*> -> resp(it.toJson())
else -> error("Invalid response type ${it.javaClass}")
} }.also { log.info("Wacca > $path : ${it.body}") }
} }
catch (e: ApiException) {
resp("[]", e.code, e.message ?: "")
}
catch (e: Exception) {
log.error("Wacca > Error", e)
resp("[]", 500, e.message ?: "")
return try {
Metrics.timer("aquadx_wacca_api_latency", "api" to path).recordCallable {
val br = JACKSON.parse<BaseRequest>(body)
handlerMap[path]!!(br, br.params).let { when (it) {
is String -> resp(it)
is List<*> -> resp(it.toJson())
else -> error("Invalid response type ${it.javaClass}")
} }.also { log.info("Wacca > $path : ${it.body}") }
}
} catch (e: Exception) {
Metrics.counter(
"aquadx_wacca_api_error",
"api" to path, "error" to e.simpleDescribe()
).increment()
if (e is ApiException) {
resp("[]", e.code, e.message ?: "")
} else {
log.error("Wacca > Error", e)
resp("[]", 500, e.message ?: "")
}
}
}
}