Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .github/workflows/be-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,6 @@ jobs:
username: ${{ secrets.BE_SERVER_USER }}
key: ${{ secrets.BE_SERVER_KEY }}
script: |
cd ~/myapp
cd ../Shared/Team2-Getit/uniro_backend
chmod +x ./deploy.sh
./deploy.sh
20 changes: 15 additions & 5 deletions uniro_backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ configurations {
compileOnly {
extendsFrom annotationProcessor
}

all {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
}

repositories {
Expand Down Expand Up @@ -88,12 +92,18 @@ dependencies {
implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'
implementation 'com.auth0:java-jwt:4.4.0'

// redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
// cache
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate6'
implementation 'com.alibaba.fastjson2:fastjson2-extension-spring6:2.0.55'
implementation 'com.github.ben-manes.caffeine:caffeine:3.1.8'

// fastjson
implementation 'com.alibaba.fastjson2:fastjson2-extension-spring6:2.0.56'

// log4j2
implementation "org.springframework.boot:spring-boot-starter-log4j2" // Spring Boot Log4j2
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml" // Jackson Dataforamt yaml
implementation "com.lmax:disruptor:3.4.4"

}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.softeer5.uniro_backend.admin.service;

import static com.softeer5.uniro_backend.common.constant.UniroConst.*;
import static com.softeer5.uniro_backend.common.error.ErrorCode.*;

import com.softeer5.uniro_backend.admin.annotation.DisableAudit;
Expand All @@ -13,7 +12,6 @@
import com.softeer5.uniro_backend.common.exception.custom.AdminException;
import com.softeer5.uniro_backend.common.exception.custom.RouteException;
import com.softeer5.uniro_backend.common.exception.custom.UnivException;
import com.softeer5.uniro_backend.external.redis.RedisService;
import com.softeer5.uniro_backend.map.dto.response.AllRoutesInfo;
import com.softeer5.uniro_backend.map.dto.response.GetChangedRoutesByRevisionResDTO;
import com.softeer5.uniro_backend.map.dto.response.GetRiskRoutesResDTO;
Expand All @@ -22,6 +20,7 @@
import com.softeer5.uniro_backend.map.entity.Route;
import com.softeer5.uniro_backend.map.repository.NodeRepository;
import com.softeer5.uniro_backend.map.repository.RouteRepository;
import com.softeer5.uniro_backend.map.cache.RouteCacheService;
import com.softeer5.uniro_backend.map.service.RouteCalculator;
import com.softeer5.uniro_backend.univ.entity.Univ;
import com.softeer5.uniro_backend.univ.repository.UnivRepository;
Expand All @@ -47,7 +46,7 @@ public class AdminService {

private final RouteCalculator routeCalculator;

private final RedisService redisService;
private final RouteCacheService cacheService;

public List<RevInfoDTO> getAllRevInfo(Long univId){

Expand Down Expand Up @@ -114,8 +113,7 @@ public void rollbackRev(Long univId, Long versionId){
}
}

int routeCount = routes.size();
redisService.deleteRoutesData(univId.toString(), routeCount / STREAM_FETCH_SIZE + 1);
cacheService.deleteFetchSizeAndLightRoutesByUnivId(univId);
}

public GetAllRoutesByRevisionResDTO getAllRoutesByRevision(Long univId, Long versionId){
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.softeer5.uniro_backend.common.config;

import java.util.concurrent.TimeUnit;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.github.benmanes.caffeine.cache.Caffeine;

@Configuration
@EnableCaching
public class CaffeineConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("lightRoutes", "tmp"); // 여러 개의 캐시 네임 설정 가능
cacheManager.setCaffeine(caffeineConfig());
return cacheManager;
}

public Caffeine<Object, Object> caffeineConfig() {
return Caffeine.newBuilder()
.expireAfterWrite(36, TimeUnit.HOURS) // 36시간 후 캐시 만료
.maximumSize(3000) // 최대 3000개 저장
.recordStats(); // 캐시 통계 활성화
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.softeer5.uniro_backend.common.config;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

Expand Down Expand Up @@ -49,6 +50,22 @@ public void addInterceptors(InterceptorRegistry registry) {
.excludePathPatterns("/**", HttpMethod.OPTIONS.name())
.order(1); // JWT 이후에 실행되도록 설정
}

@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
config.setReaderFeatures(JSONReader.Feature.FieldBased, JSONReader.Feature.SupportArrayToBean);
config.setWriterFeatures(JSONWriter.Feature.WriteMapNullValue);
converter.setFastJsonConfig(config);
converter.setDefaultCharset(StandardCharsets.UTF_8);
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
converter.setSupportedMediaTypes(supportedMediaTypes);
converters.add(0, converter);
}
}


Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.softeer5.uniro_backend.common.logging;

import static com.softeer5.uniro_backend.common.constant.UniroConst.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
Expand All @@ -8,21 +12,26 @@
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;

@Aspect
@Component
@Log4j2
@Slf4j
@Profile("!test")
public class ExecutionLoggingAop {
Logger asyncLogger = LoggerFactory.getLogger("async-logger");
Logger synclogger = LoggerFactory.getLogger(ExecutionLoggingAop.class);

private static final ThreadLocal<String> userIdThreadLocal = new ThreadLocal<>();

Expand All @@ -48,44 +57,41 @@ public Object logExecutionTrace(ProceedingJoinPoint pjp) throws Throwable {
}
HttpServletRequest request = null;
if (RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes) {
request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
}

if(request==null){
if (request == null) {
return pjp.proceed();
}
log.info("✅ [ userId = {} Start] [Call Method] {}: {}", userId, request.getMethod(), task);
asyncLogger.info("✅ [ userId = {} Start] [Call Method] {}: {}", userId, request.getMethod(), task);

try{
try {
if (isController) {
logParameters(pjp.getArgs());
}
}
catch (Exception e){
} catch (Exception e) {
// 로깅 중에 발생한 에러는 무시하고 로깅을 계속 진행
log.error("🚨🚨🚨 [ userId = {} ] {} 메서드 파라미터 로깅 중 에러 발생 : {} 🚨🚨🚨", userId, task, e.getMessage());
asyncLogger.error("🚨🚨🚨 [ userId = {} ] {} 메서드 파라미터 로깅 중 에러 발생 : {} 🚨🚨🚨", userId, task, e.getMessage());
}
log.info("");

StopWatch sw = new StopWatch();
sw.start();

Object result;
try {
result = pjp.proceed();
sw.stop();
asyncLogger.info("🚨 [ExecutionTime] {} --> {} (ms) [ userId = {} ] {} End\n", task, sw.getTotalTimeMillis(),
userId, className);
} catch (Exception e) {
log.warn("[ERROR] [ userId = {} ] {} 메서드 예외 발생 : {}", userId, task, e.getMessage());
asyncLogger.warn("[ERROR] [ userId = {} ] {} 메서드 예외 발생 : {}", userId, task, e.getMessage());
throw e;
} finally {
if (isController) {
if (isControllerOrService(target)) {
userIdThreadLocal.remove();
}
}

sw.stop();
log.info("[ExecutionTime] {} --> {} (ms)", task, sw.getTotalTimeMillis());
log.info("🚨 [ userId = {} ] {} End\n", userId, className);

return result;
}

Expand All @@ -94,13 +100,23 @@ private boolean isRestController(Object target) {
.anyMatch(RestController.class::isInstance);
}

private boolean isControllerOrService(Object target) {
boolean b = Arrays.stream(target.getClass().getDeclaredAnnotations())
.anyMatch(RestController.class::isInstance);

boolean b1 = Arrays.stream(target.getClass().getDeclaredAnnotations())
.anyMatch(Service.class::isInstance);

return b || b1;
}

private void logParameters(Object[] args) {
StringBuilder parametersLogMessage = new StringBuilder();

Arrays.stream(args)
.forEach(arg -> logDetail(arg, "[Parameter]", parametersLogMessage, 0));

log.info("\n{}", parametersLogMessage.toString());
asyncLogger.info("\n{}", parametersLogMessage);
}

private void logDetail(Object arg, String requestType, StringBuilder logMessage, int depth) {
Expand Down Expand Up @@ -154,13 +170,16 @@ private void logObjectFields(Object object, StringBuilder logMessage, int depth)
Object value = field.get(object);
logDetail(value, "[Field] " + field.getName(), logMessage, depth + 1);
} catch (IllegalAccessException e) {
logMessage.append(indent).append("[Field Access Error] Cannot access field: ").append(field.getName()).append("\n");
logMessage.append(indent)
.append("[Field Access Error] Cannot access field: ")
.append(field.getName())
.append("\n");
}
});
}

private void logHttpRequest(String userId) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();

// HTTP Request 메시지 출력 (RFC 2616 형식)
StringBuilder httpMessage = new StringBuilder();
Expand Down Expand Up @@ -199,7 +218,6 @@ private void logHttpRequest(String userId) {
}

// 요청 메시지 출력
log.info("✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ New request");
log.info("[ userId = "+ userId + " ] HTTP Request: \n" + httpMessage);
asyncLogger.info("✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ New request\n [ userId = {} ] HTTP Request: {} \n", userId, httpMessage);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.softeer5.uniro_backend.map.cache;

import com.softeer5.uniro_backend.map.service.vo.LightRoutes;

public interface RouteCacheService {
LightRoutes getLightRoutes(Long univId, int batchNumber);

void saveLightRoutes(Long univId, int batchNumber, LightRoutes value);

boolean hasLightRoutes(Long univId, int batchNumber);

Integer getFetchSize(Long univId);

void saveFetchSize(Long univId, Integer fetchSize);

boolean hasFetchSize(Long univId);

void deleteFetchSizeAndLightRoutesByUnivId(Long univId);
}
Loading