Skip to content

Commit

Permalink
version 2.6.10
Browse files Browse the repository at this point in the history
* [Refactor] Log refactor

* refactor: Log level 변경

* refactor: 환경 별 Log Setting 변경 완료

* refactor: 로그파일 저장 기간을 10일로 단축

* refactor(FirebaseNotificationService): message 변환 로직을 메서드로 추출

* test(AdminAcceptanceTest): 관리자의 공지 전송 인수테스트 작성

* feat(start.sh): 프로젝트 루트로 이동하는 라인 추가
  • Loading branch information
zbqmgldjfh authored May 26, 2024
1 parent 9f8fb91 commit fa1ba8c
Show file tree
Hide file tree
Showing 24 changed files with 242 additions and 118 deletions.
8 changes: 4 additions & 4 deletions scripts/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

PROJECT_ROOT="/home/ec2-user/app"
JAR_FILE="$PROJECT_ROOT/spring-webapp.jar"

APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)
Expand All @@ -15,10 +12,13 @@ source ~/.bash_profile
echo "$TIME_NOW > $JAR_FILE 파일 복사" >> $DEPLOY_LOG
cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE

# 프로젝트 루트로 이동
cd $PROJECT_ROOT

# jar 파일 실행
chmod 755 $JAR_FILE
echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG
nohup java -jar -Dspring.profiles.active=prod -Xms256m -Xmx256m $JAR_FILE > $APP_LOG 2> $ERROR_LOG &
nohup java -jar -Dspring.profiles.active=prod -Xms256m -Xmx256m $JAR_FILE &

CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG
Original file line number Diff line number Diff line change
Expand Up @@ -22,55 +22,55 @@ public class CommonExceptionHandler {

@ExceptionHandler
public ResponseEntity<ErrorResponse> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException exception) {
log.error("[MethodArgumentNotValidException] {}", exception.getMessage());
log.warn("[MethodArgumentNotValidException] {}", exception.getMessage());
return ResponseEntity.status(ErrorCode.API_MISSING_PARAM.getHttpStatus())
.body(new ErrorResponse(ErrorCode.API_MISSING_PARAM));
}

@ExceptionHandler
public ResponseEntity<ErrorResponse> NotFoundExceptionHandler(NotFoundException exception) {
log.error("[NotFoundException] {}", exception.getMessage());
log.warn("[NotFoundException] {}", exception.getMessage());
return ResponseEntity.status(exception.getErrorCode().getHttpStatus())
.body(new ErrorResponse(exception.getErrorCode()));
}

@ExceptionHandler(AdminException.class)
public ResponseEntity<ErrorResponse> AdminExceptionHandler(AdminException exception) {
log.error("[APIException] {}", exception.getErrorCode().getMessage(), exception);
log.warn("[APIException] {}", exception.getErrorCode().getMessage(), exception);
return ResponseEntity.status(exception.getErrorCode().getHttpStatus())
.body(new ErrorResponse(exception.getErrorCode()));
}

@ExceptionHandler
public ResponseEntity<ErrorResponse> MissingServletRequestParameterExceptionHandler(MissingServletRequestParameterException exception) {
log.error("[MissingServletRequestParameterException] {}", exception.getMessage());
log.warn("[MissingServletRequestParameterException] {}", exception.getMessage());
return ResponseEntity.status(ErrorCode.API_MISSING_PARAM.getHttpStatus())
.body(new ErrorResponse(ErrorCode.API_MISSING_PARAM));
}

@ExceptionHandler
public ResponseEntity<ErrorResponse> ConstraintViolationExceptionHandler(ConstraintViolationException exception) {
log.error("[ConstraintViolationException] {}", exception.getMessage());
log.warn("[ConstraintViolationException] {}", exception.getMessage());
return ResponseEntity.status(ErrorCode.API_INVALID_PARAM.getHttpStatus())
.body(new ErrorResponse(ErrorCode.API_INVALID_PARAM));
}

@ExceptionHandler
public ResponseEntity<ErrorResponse> HttpMediaTypeNotAcceptableExceptionHandler(HttpMediaTypeNotAcceptableException exception) {
log.error("[HttpMediaTypeNotAcceptableException] {}", exception.getMessage());
log.warn("[HttpMediaTypeNotAcceptableException] {}", exception.getMessage());
return ResponseEntity.status(ErrorCode.API_NOT_ACCEPTABLE.getHttpStatus())
.body(new ErrorResponse(ErrorCode.API_NOT_ACCEPTABLE));
}

@ExceptionHandler
public ResponseEntity<ErrorResponse> FirebaseSubscribeExceptionHandler(FirebaseSubscribeException exception) {
log.error("[FirebaseSubscribeException] {}", exception.getMessage());
log.warn("[FirebaseSubscribeException] {}", exception.getMessage());
return ResponseEntity.status(ErrorCode.API_FB_SERVER_ERROR.getHttpStatus())
.body(new ErrorResponse(ErrorCode.API_FB_SERVER_ERROR));
}

@ExceptionHandler
public void InternalLogicExceptionHandler(InternalLogicException e) {
log.error("[InternalLogicException] {}", e.getErrorCode().getMessage(), e);
log.warn("[InternalLogicException] {}", e.getErrorCode().getMessage(), e);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class FirebaseExceptionHandler {

@ExceptionHandler
public ResponseEntity<ErrorResponse> firebaseCommonExceptionHandler(FirebaseBusinessException exception) {
log.error("[FirebaseBusinessException] {}", exception.getMessage());
log.warn("[FirebaseBusinessException] {}", exception.getMessage());

return ResponseEntity.status(exception.getErrorCode().getHttpStatus())
.body(new ErrorResponse(exception.getErrorCode()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
import com.kustacks.kuring.message.application.service.exception.FirebaseSubscribeException;
import com.kustacks.kuring.message.application.service.exception.FirebaseUnSubscribeException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

import java.util.List;

@Slf4j
@Component
@Profile("prod | dev")
@RequiredArgsConstructor
Expand All @@ -44,6 +46,7 @@ public void subscribeToTopic(
TopicManagementResponse response = firebaseMessaging.subscribeToTopic(tokens, topic);

if (response.getFailureCount() > 0) {
log.warn("[{}] 구독 실패", tokens.get(0));
throw new FirebaseSubscribeException();
}
} catch (FirebaseMessagingException | FirebaseSubscribeException exception) {
Expand All @@ -60,6 +63,7 @@ public void unsubscribeFromTopic(
TopicManagementResponse response = firebaseMessaging.unsubscribeFromTopic(tokens, topic);

if (response.getFailureCount() > 0) {
log.warn("[{}] 구독 취소 실패", tokens.get(0));
throw new FirebaseUnSubscribeException();
}
} catch (FirebaseMessagingException | FirebaseUnSubscribeException exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,32 +52,23 @@ public void sendTestNotificationByAdmin(AdminTestNotificationCommand command) {
@Override
public void sendNotificationByAdmin(AdminNotificationCommand command) {
try {
Message newMessage = Message.builder()
.setNotification(Notification
.builder()
.setTitle(command.title())
.setBody(command.body())
.build())
.putAllData(objectMapper.convertValue(command, Map.class))
.setTopic(serverProperties.ifDevThenAddSuffix(ALL_DEVICE_SUBSCRIBED_TOPIC))
.build();

Message newMessage = createMessageFromCommand(command);
firebaseMessagingPort.send(newMessage);
} catch (FirebaseMessagingException exception) {
throw new FirebaseMessageSendException();
}
}

public void sendNotificationList(List<? extends Notice> noticeList) {
public void sendNotifications(List<? extends Notice> noticeList) {
List<NoticeMessageDto> notificationDtoList = createNotification(noticeList);
if (notificationDtoList.isEmpty()) {
log.info("새로운 공지가 없습니다.");
return;
}

try {
this.sendNoticeMessageList(notificationDtoList);
log.info("FCM에 {}개의 공지 메세지를 전송했습니다.", notificationDtoList.size());
log.info("전송된 공지 목록은 다음과 같습니다.");
for (Notice notice : noticeList) {
log.info("아이디 = {}, 날짜 = {}, 카테고리 = {}, 제목 = {}", notice.getArticleId(), notice.getPostedDate(), notice.getCategoryName(), notice.getSubject());
}
loggingNoticeSendInfo(notificationDtoList);
this.sendNoticeMessages(notificationDtoList);
} catch (FirebaseMessageSendException e) {
log.error("새로운 공지의 FCM 전송에 실패했습니다.");
throw new InternalLogicException(ErrorCode.FB_FAIL_SEND, e);
Expand All @@ -87,6 +78,21 @@ public void sendNotificationList(List<? extends Notice> noticeList) {
}
}

private void loggingNoticeSendInfo(List<NoticeMessageDto> notificationDtoList) {
log.info("FCM에 {}카테고리에 {}개의 공지 메세지를 전송.",
notificationDtoList.get(0).getCategory(), notificationDtoList.size());

log.info("전송된 공지 목록은 다음과 같습니다.");
for (NoticeMessageDto noticeMessageDto : notificationDtoList) {
log.info("아이디 = {}, 날짜 = {}, 카테고리 = {}, 제목 = {}",
noticeMessageDto.getArticleId(),
noticeMessageDto.getPostedDate(),
noticeMessageDto.getCategory(),
noticeMessageDto.getSubject()
);
}
}

/**
* Firebase message에는 두 가지 paylaad가 존재한다.
* 1. notification
Expand All @@ -104,31 +110,49 @@ private void sendNotification(NoticeMessageDto messageDto) throws FirebaseMessag
sendBaseNotification(messageDto, serverProperties::ifDevThenAddSuffix);
}

private void sendBaseNotification(NoticeMessageDto messageDto, UnaryOperator<String> suffixUtil) throws FirebaseMessageSendException {
private void sendBaseNotification(
NoticeMessageDto messageDto,
UnaryOperator<String> suffixUtil
) throws FirebaseMessageSendException {
try {
Message newMessage = Message.builder()
.setNotification(Notification
.builder()
.setTitle(buildTitle(messageDto.getCategoryKorName()))
.setBody(messageDto.getSubject())
.build())
.putAllData(objectMapper.convertValue(messageDto, Map.class))
.setTopic(suffixUtil.apply(messageDto.getCategory()))
.build();

Message newMessage = createMessageFromDto(messageDto, suffixUtil);
firebaseMessagingPort.send(newMessage);
} catch (FirebaseMessagingException exception) {
throw new FirebaseMessageSendException();
}
}

private Message createMessageFromCommand(AdminNotificationCommand command) {
return Message.builder()
.setNotification(Notification
.builder()
.setTitle(command.title())
.setBody(command.body())
.build())
.putAllData(objectMapper.convertValue(command, Map.class))
.setTopic(serverProperties.ifDevThenAddSuffix(ALL_DEVICE_SUBSCRIBED_TOPIC))
.build();
}

private Message createMessageFromDto(NoticeMessageDto messageDto, UnaryOperator<String> suffixUtil) {
return Message.builder()
.setNotification(Notification
.builder()
.setTitle(buildTitle(messageDto.getCategoryKorName()))
.setBody(messageDto.getSubject())
.build())
.putAllData(objectMapper.convertValue(messageDto, Map.class))
.setTopic(suffixUtil.apply(messageDto.getCategory()))
.build();
}

private List<NoticeMessageDto> createNotification(List<? extends Notice> willBeNotiNotices) {
return willBeNotiNotices.stream()
.map(NoticeMessageDto::from)
.toList();
}

private void sendNoticeMessageList(List<NoticeMessageDto> messageDtoList) throws FirebaseMessageSendException {
private void sendNoticeMessages(List<NoticeMessageDto> messageDtoList) throws FirebaseMessageSendException {
messageDtoList.forEach(this::sendNotification);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public class DepartmentNoticeScraperTemplate {
public List<ComplexNoticeFormatDto> scrap(DeptInfo deptInfo, Function<DeptInfo, List<ScrapingResultDto>> decisionMaker) throws InternalLogicException {
List<ScrapingResultDto> requestResults = requestWithDeptInfo(deptInfo, decisionMaker);

log.info("[{}] HTML 파싱 시작", deptInfo.getDeptName());
log.debug("[{}] HTML 파싱 시작", deptInfo.getDeptName());
List<ComplexNoticeFormatDto> noticeDtoList = htmlParsingFromScrapingResult(deptInfo, requestResults);
log.info("[{}] HTML 파싱 완료", deptInfo.getDeptName());
log.debug("[{}] HTML 파싱 완료", deptInfo.getDeptName());

for (ComplexNoticeFormatDto complexNoticeFormatDto : noticeDtoList) {
if (complexNoticeFormatDto.getNormalNoticeSize() == 0) {
Expand All @@ -38,12 +38,12 @@ public List<ComplexNoticeFormatDto> scrap(DeptInfo deptInfo, Function<DeptInfo,
private List<ScrapingResultDto> requestWithDeptInfo(DeptInfo deptInfo, Function<DeptInfo, List<ScrapingResultDto>> decisionMaker) {
long startTime = System.currentTimeMillis();

log.info("[{}] HTML 요청", deptInfo.getDeptName());
log.debug("[{}] HTML 요청", deptInfo.getDeptName());
List<ScrapingResultDto> reqResults = decisionMaker.apply(deptInfo);
log.info("[{}] HTML 수신", deptInfo.getDeptName());
log.debug("[{}] HTML 수신", deptInfo.getDeptName());

long endTime = System.currentTimeMillis();
log.info("[{}] 파싱에 소요된 초 = {}", deptInfo.getDeptName(), (endTime - startTime) / 1000.0);
log.debug("[{}] 파싱에 소요된 초 = {}", deptInfo.getDeptName(), (endTime - startTime) / 1000.0);

return reqResults;
}
Expand All @@ -57,7 +57,7 @@ private List<ComplexNoticeFormatDto> htmlParsingFromScrapingResult(DeptInfo dept
RowsDto rowsDto = deptInfo.parse(document);
List<CommonNoticeFormatDto> importantNoticeFormatDtos = rowsDto.buildImportantRowList(viewUrl);
List<CommonNoticeFormatDto> normalNoticeFormatDtos = rowsDto.buildNormalRowList(viewUrl);
log.info("[{}] 공지 개수 = {}", deptInfo.getDeptName(), importantNoticeFormatDtos.size() + normalNoticeFormatDtos.size());
log.debug("[{}] 공지 개수 = {}", deptInfo.getDeptName(), importantNoticeFormatDtos.size() + normalNoticeFormatDtos.size());
noticeDtoList.add(new ComplexNoticeFormatDto(importantNoticeFormatDtos, normalNoticeFormatDtos));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,46 +19,60 @@
@Component
public class KuisHomepageNoticeScraperTemplate {

public List<ComplexNoticeFormatDto> scrap(KuisHomepageNoticeInfo kuisNoticeInfo, Function<KuisHomepageNoticeInfo, List<ScrapingResultDto>> decisionMaker) throws InternalLogicException {
public List<ComplexNoticeFormatDto> scrap(
KuisHomepageNoticeInfo kuisNoticeInfo,
Function<KuisHomepageNoticeInfo, List<ScrapingResultDto>> decisionMaker
) throws InternalLogicException {
List<ScrapingResultDto> requestResults = requestWithDeptInfo(kuisNoticeInfo, decisionMaker);

log.info("[{}] HTML 파싱 시작", kuisNoticeInfo.getCategoryName());
log.debug("[{}] HTML 파싱 시작", kuisNoticeInfo.getCategoryName());
List<ComplexNoticeFormatDto> noticeDtoList = htmlParsingFromScrapingResult(kuisNoticeInfo, requestResults);
log.info("[{}] HTML 파싱 완료", kuisNoticeInfo.getCategoryName());
log.debug("[{}] HTML 파싱 완료", kuisNoticeInfo.getCategoryName());

validateScrapedNoticeCountIsNotZero(noticeDtoList);

return noticeDtoList;
}

private void validateScrapedNoticeCountIsNotZero(List<ComplexNoticeFormatDto> noticeDtoList) {
for (ComplexNoticeFormatDto complexNoticeFormatDto : noticeDtoList) {
if (complexNoticeFormatDto.getNormalNoticeSize() == 0) {
throw new InternalLogicException(ErrorCode.NOTICE_SCRAPER_CANNOT_SCRAP);
}
}

return noticeDtoList;
}

private List<ScrapingResultDto> requestWithDeptInfo(KuisHomepageNoticeInfo kuisNoticeInfo, Function<KuisHomepageNoticeInfo, List<ScrapingResultDto>> decisionMaker) {
private List<ScrapingResultDto> requestWithDeptInfo(
KuisHomepageNoticeInfo kuisNoticeInfo,
Function<KuisHomepageNoticeInfo, List<ScrapingResultDto>> decisionMaker
) {
long startTime = System.currentTimeMillis();

log.info("[{}] HTML 요청", kuisNoticeInfo.getCategoryName());
log.debug("[{}] HTML 요청", kuisNoticeInfo.getCategoryName());
List<ScrapingResultDto> reqResults = decisionMaker.apply(kuisNoticeInfo);
log.info("[{}] HTML 수신", kuisNoticeInfo.getCategoryName());
log.debug("[{}] HTML 수신", kuisNoticeInfo.getCategoryName());

long endTime = System.currentTimeMillis();
log.info("[{}] 파싱에 소요된 초 = {}", kuisNoticeInfo.getCategoryName(), (endTime - startTime) / 1000.0);
log.debug("[{}] 파싱에 소요된 초 = {}", kuisNoticeInfo.getCategoryName(), (endTime - startTime) / 1000.0);

return reqResults;
}


private List<ComplexNoticeFormatDto> htmlParsingFromScrapingResult(KuisHomepageNoticeInfo kuisNoticeInfo, List<ScrapingResultDto> requestResults) {
private List<ComplexNoticeFormatDto> htmlParsingFromScrapingResult(
KuisHomepageNoticeInfo kuisNoticeInfo,
List<ScrapingResultDto> requestResults
) {
List<ComplexNoticeFormatDto> noticeDtoList = new LinkedList<>();

for (ScrapingResultDto reqResult : requestResults) {
Document document = reqResult.getDocument();
String viewUrl = reqResult.getViewUrl();

RowsDto rowsDto = kuisNoticeInfo.parse(document);
List<CommonNoticeFormatDto> importantNoticeFormatDtos = rowsDto.buildImportantRowList(viewUrl);
List<CommonNoticeFormatDto> normalNoticeFormatDtos = rowsDto.buildNormalRowList(viewUrl);
log.info("[{}] 공지 개수 = {}", kuisNoticeInfo.getCategoryName(), importantNoticeFormatDtos.size() + normalNoticeFormatDtos.size());
log.debug("[{}] 공지 개수 = {}", kuisNoticeInfo.getCategoryName(), importantNoticeFormatDtos.size() + normalNoticeFormatDtos.size());
noticeDtoList.add(new ComplexNoticeFormatDto(importantNoticeFormatDtos, normalNoticeFormatDtos));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ private List<CommonNoticeFormatDto> requestWithKuisInfo(KuisNoticeInfo kuisNotic
List<CommonNoticeFormatDto> requestResults = decisionMaker.apply(kuisNoticeRequestBody);
long endTime = System.currentTimeMillis();

log.info("[{}] 파싱에 소요된 초 = {}", kuisNoticeRequestBody.getCategoryName().getName(), (endTime - startTime) / 1000.0);
log.debug("[{}] 파싱에 소요된 초 = {}", kuisNoticeRequestBody.getCategoryName().getName(), (endTime - startTime) / 1000.0);
return requestResults;
}
}
Loading

0 comments on commit fa1ba8c

Please sign in to comment.