Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] 모니터링 구현 #57

Merged
merged 8 commits into from
Dec 11, 2024
12 changes: 8 additions & 4 deletions wabi/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ repositories {
}

dependencies {
//Monitoring
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("io.micrometer:micrometer-registry-prometheus")

//QueryDSL
implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta")
implementation("com.querydsl:querydsl-apt:5.0.0:jakarta")
Expand All @@ -40,10 +44,10 @@ dependencies {
implementation("org.apache.poi:poi-ooxml:5.2.3")

//jwt
implementation ("org.springframework.boot:spring-boot-starter-security")
implementation ("io.jsonwebtoken:jjwt-api:0.11.5")
implementation ("io.jsonwebtoken:jjwt-impl:0.11.5")
implementation ("io.jsonwebtoken:jjwt-jackson:0.11.5")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("io.jsonwebtoken:jjwt-api:0.11.5")
implementation("io.jsonwebtoken:jjwt-impl:0.11.5")
implementation("io.jsonwebtoken:jjwt-jackson:0.11.5")

implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
Expand Down
2 changes: 2 additions & 0 deletions wabi/src/main/kotlin/com/wap/wabi/WabiApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import jakarta.annotation.PostConstruct
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.data.jpa.repository.config.EnableJpaAuditing
import org.springframework.scheduling.annotation.EnableScheduling
import java.util.TimeZone

@SpringBootApplication
@EnableJpaAuditing
@EnableScheduling
class WabiApplication {
@PostConstruct
fun started() {
Expand Down
13 changes: 13 additions & 0 deletions wabi/src/main/kotlin/com/wap/wabi/auth/admin/entity/Admin.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,17 @@ public Admin build() {
return new Admin(this);
}
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Admin admin = (Admin) o;
return id.equals(admin.id);
}

@Override
public int hashCode() {
return id.hashCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.wap.wabi.auth.admin.payload.response.AdminLoginResponse
import com.wap.wabi.auth.admin.repository.AdminRefreshTokenRepository
import com.wap.wabi.auth.admin.repository.AdminRepository
import com.wap.wabi.auth.admin.util.AdminValidator
import com.wap.wabi.auth.admin.util.UserActivityManager
import com.wap.wabi.auth.jwt.JwtTokenProvider
import com.wap.wabi.exception.ErrorCode
import com.wap.wabi.exception.RestApiException
Expand All @@ -20,7 +21,8 @@ class AdminService(
private val adminRefreshTokenRepository: AdminRefreshTokenRepository,
private val tokenProvider: JwtTokenProvider,
private val adminValidator: AdminValidator,
private val encoder: PasswordEncoder
private val encoder: PasswordEncoder,
private val userActivityManager: UserActivityManager
) {
@Transactional
fun registerAdmin(adminRegisterRequest: AdminRegisterRequest) {
Expand All @@ -36,7 +38,11 @@ class AdminService(
adminValidator.validateLogin(adminLoginRequest)
val admin = adminRepository.findByName(adminLoginRequest.name)
?.takeIf { admin ->
encoder.matches(adminLoginRequest.password, admin.get().password)
try {
encoder.matches(adminLoginRequest.password, admin.get().password)
} catch (e: Exception) {
throw RestApiException(ErrorCode.BAD_REQUEST_ADMIN_LOGIN)
}
}
?: throw RestApiException(ErrorCode.BAD_REQUEST_NOT_EXIST_ADMIN)
val refreshToken = tokenProvider.createRefreshToken()
Expand All @@ -54,6 +60,7 @@ class AdminService(
)

val accessToken = tokenProvider.createAccessToken("${admin.get().username}:${admin.get().role}")
userActivityManager.updateUserActivity(admin.get())
return AdminLoginResponse(
name = admin.get().username,
role = admin.get().role,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.wap.wabi.auth.admin.util

import com.wap.wabi.auth.admin.entity.Admin
import io.micrometer.core.instrument.Gauge
import io.micrometer.core.instrument.Metrics
import org.slf4j.LoggerFactory
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component


@Component
class UserActivityManager {
private var dauCounter = 0
private var mauCounter = 0

private val activeUsersToday = HashSet<Admin>()

private val logger = LoggerFactory.getLogger(UserActivityManager::class.java)

fun updateUserActivity(admin: Admin) {
if (activeUsersToday.add(admin)) {
dauCounter++
mauCounter++
}

Gauge.builder("user_activity_dau") { dauCounter }.register(Metrics.globalRegistry)
Gauge.builder("user_activity_mau") { mauCounter }.register(Metrics.globalRegistry)
}

@Scheduled(cron = "0 0 0 * * ?")
fun resetDailyActiveUser() {
dauCounter = 0
activeUsersToday.clear()
logger.info("Reset daily active user")
}

@Scheduled(cron = "0 0 0 1 * ?")
fun resetMonthlyActiveUser() {
mauCounter = 0
logger.info("Reset monthly active user")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class SecurityConfig(
.requestMatchers(
"/swagger-ui/**",
"/v3/api-docs/**",
"/health"
"/health",
"/actuator/**"
).permitAll()
.anyRequest().authenticated()
}.sessionManagement { session ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,13 @@ class JwtAuthenticationFilter(
response: HttpServletResponse,
filterChain: FilterChain
) {
val path = request.requestURI
if (path.startsWith("/swagger-ui/") || path.startsWith("/v3") || path.startsWith("/auth")) {
filterChain.doFilter(request, response)
return
}

try {
parseBearerToken(request, HttpHeaders.AUTHORIZATION)?.let { accessToken ->
jwtTokenProvider.validateAndParseToken(accessToken)

val user = parseUserSpecification(accessToken)
val authentication = UsernamePasswordAuthenticationToken.authenticated(user, accessToken, user.authorities)
val authentication =
UsernamePasswordAuthenticationToken.authenticated(user, accessToken, user.authorities)
authentication.details = WebAuthenticationDetails(request)
SecurityContextHolder.getContext().authentication = authentication
}
Expand All @@ -45,9 +40,7 @@ class JwtAuthenticationFilter(
return // 새 토큰 발급 후 요청 종료
}
} catch (e: Exception) {
response.status = HttpServletResponse.SC_UNAUTHORIZED
response.writer.write("Invalid Token")
return
logger.info("No Token")
}

filterChain.doFilter(request, response)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class RequestLoggingInterceptor : HandlerInterceptor {
private val logger = LoggerFactory.getLogger(RequestLoggingInterceptor::class.java)

override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
logger.info("Request received from" + request.remoteAddr + "to" + request.requestURI)
logger.info("Request received from " + request.remoteAddr + " to" + request.requestURI)
return true
}
}
1 change: 1 addition & 0 deletions wabi/src/main/kotlin/com/wap/wabi/exception/ErrorCode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ enum class ErrorCode(
BAD_REQUEST_ADMIN_NAME(HttpStatus.BAD_REQUEST, "800-3", "이름이 형식에 맞지 않습니다."),
BAD_REQUEST_EXIST_ADMIN(HttpStatus.BAD_REQUEST, "800-4", "이미 존재하는 어드민입니다."),
BAD_REQUEST_NOT_EXIST_ADMIN(HttpStatus.BAD_REQUEST, "800-5", "존재하지 않는 어드민입니다."),
BAD_REQUEST_ADMIN_LOGIN(HttpStatus.BAD_REQUEST, "800-6", "일치하는 계정이 없습니다."),
}
2 changes: 2 additions & 0 deletions wabi/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
spring.application.name=wabi
spring.profiles.active=prod
management.endpoints.web.exposure.include=prometheus, health, info
management.metrics.tags.application=${spring.application.name}
Loading