diff --git a/.github/legacies/monitor_downtime.sh b/.github/legacies/monitor_downtime.sh deleted file mode 100644 index 539f7e9..0000000 --- a/.github/legacies/monitor_downtime.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -WEBHOOK="$1" -# 내부 호출이므로 localhost 고정 -TARGET="http://localhost:8080/status" -TIMEOUT=180 -HOST_NAME=$(hostname) - -# Slack 전송 함수 -function send_slack() { - local MESSAGE="$1" - - # 1. 봇 이름 및 아이콘 설정 - local USERNAME="배포 상태 알림이" - local ICON=":rocket:" - - # 2. 메시지 내용에 따라 아이콘 동적 변경 (선택 사항) - # 실패/Time out 문구가 있으면 경광등(:rotating_light:)으로 변경 - if [[ "$MESSAGE" == *"실패"* ]] || [[ "$MESSAGE" == *"Time out"* ]]; then - ICON=":rotating_light:" - elif [[ "$MESSAGE" == *"완료"* ]]; then - ICON=":white_check_mark:" - fi - - local PAYLOAD=$(cat < /dev/null -} - -# 1. 초기 상태 확인 -# -s: Silent, -o /dev/null: 출력 버림, -w: HTTP 코드만 출력 -STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$TARGET") - -# [수정됨] 배포 전인데 이미 서버가 죽어있다면 알림을 보내고 종료 -if [ "$STATUS" -ne 200 ]; then - send_slack "⚠️ *모니터링 건너뜀*\n- 서버: ${HOST_NAME}\n- 원인: 배포 전 이미 비정상 상태 (Status: ${STATUS})" - exit 0 -fi - -send_slack "🚀 *배포 모니터링 시작*\n- 서버: ${HOST_NAME}\n- 상태: 다운타임 측정 대기 중" - -START_WAIT=$(date +%s) -DOWNTIME_START=0 -DOWNTIME_END=0 - -# 2. 다운타임 시작 감지 (서버가 죽을 때까지) -while true; do - CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 1 "$TARGET") - if [ "$CODE" -ne 200 ]; then - DOWNTIME_START=$(date +%s) - send_slack "🚀 *배포 모니터링 시작*\n- 서버: ${HOST_NAME}\n- 상태: 다운타임 측정 시작" - break - fi - # 타임아웃 체크 - if [ $(( $(date +%s) - START_WAIT )) -gt $TIMEOUT ]; then - send_slack "❌ *배포 실패 (Time out)*\n- 서버: ${HOST_NAME}\n- 원인: 기존 서버가 중단되지 않음" - exit 1 - fi - sleep 0.5 -done - -# 3. 서비스 복구 감지 (서버가 살 때까지) -while true; do - CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 1 "$TARGET") - if [ "$CODE" -eq 200 ]; then - DOWNTIME_END=$(date +%s) - break - fi - if [ $(( $(date +%s) - DOWNTIME_START )) -gt $TIMEOUT ]; then - send_slack "❌ *배포 실패 (Time out)*\n- 서버: ${HOST_NAME}\n- 원인: 신규 서버가 구동되지 않음" - exit 1 - fi - sleep 1 -done - -DURATION=$((DOWNTIME_END - DOWNTIME_START)) - -# 4. 완료 Slack 전송 -send_slack "✅ *배포 완료 및 서비스 정상화*\n- 서버: ${HOST_NAME}\n- 다운타임: *${DURATION}초*" \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 60eee03..84fe776 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,6 +4,10 @@ plugins { id "de.undercouch.download" version "5.3.0" } +version = rootProject.version +group = rootProject.group + + dependencies { implementation project(':auth:auth-impl') @@ -14,8 +18,8 @@ dependencies { annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' } -tasks.named("jib") { - dependsOn "generateJmxConfigFiles" +springBoot { + buildInfo() } jib { @@ -36,14 +40,6 @@ jib { setFrom(file("newrelic").toPath()) into = "/app/newrelic" } - path { - setFrom(layout.buildDirectory.dir("jmx")) - into = "/app/jmx" - permissions = [ - '/app/jmx/jmxremote.password': '600', - '/app/jmx/jmxremote.access' : '600' - ] - } } } container { @@ -57,37 +53,7 @@ jib { jvmFlags = jvmFlags + [ "-Dnewrelic.config.file=/app/newrelic/newrelic.yml", "-javaagent:/app/newrelic/newrelic.jar", - "-Dcom.sun.management.jmxremote", - "-Dcom.sun.management.jmxremote.port=9999", - "-Dcom.sun.management.jmxremote.rmi.port=9999", - "-Dcom.sun.management.jmxremote.authenticate=true", - "-Dcom.sun.management.jmxremote.ssl=false", - "-Djava.rmi.server.hostname=dev-api.q-asker.com", - "-Dcom.sun.management.jmxremote.access.file=/app/jmx/jmxremote.access", - "-Dcom.sun.management.jmxremote.password.file=/app/jmx/jmxremote.password" ] } } -} - -tasks.register("generateJmxConfigFiles") { - group = "build" - - def outputDirProvider = layout.buildDirectory.dir("jmx") - outputs.dir(outputDirProvider) - - def id = project.property("JMX_ID") - def password = project.property("JMX_PASSWORD") - - doLast { - def actualOutputDir = outputDirProvider.get().asFile - actualOutputDir.mkdirs() - - new File(actualOutputDir, "jmxremote.access").text = - "$id readwrite" - - new File(actualOutputDir, "jmxremote.password").text = - "$id $password" - - } } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 960f46d..5284df7 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { group = "com.icc.qasker" -version = "1.6.1" +version = "1.6.2" subprojects { apply plugin: 'java' diff --git a/monitor_downtime.sh b/monitor_downtime.sh new file mode 100755 index 0000000..89844f4 --- /dev/null +++ b/monitor_downtime.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +# ========================================== +# 설정 (본인 환경에 맞게 수정하세요) +# ========================================== +URL="http://dev-api.q-asker.com:8080/actuator/info" +SLEEP_SEC=0.1 +# ========================================== + +echo "Checking initial version from $URL..." + +# 1. 초기 버전 확인 (현재 실행 중인 버전) +INITIAL_RESPONSE=$(curl -s -m 2 "$URL") +if [ -z "$INITIAL_RESPONSE" ]; then + echo "Error: Cannot connect to server to get initial version." + exit 1 +fi + +OLD_VERSION=$(echo "$INITIAL_RESPONSE" | jq -r '.build.version') + +if [ "$OLD_VERSION" == "null" ] || [ -z "$OLD_VERSION" ]; then + echo "Error: Could not parse version from JSON. Check if 'build.version' exists." + echo "Response: $INITIAL_RESPONSE" + exit 1 +fi + +echo "-----------------------------------------------------" +echo "TARGET URL : $URL" +echo "CURRENT VERSION : $OLD_VERSION" +echo "Scanning for new version every $SLEEP_SEC seconds..." +echo "-----------------------------------------------------" + +# 변수 초기화 +START_TIME=$(date +%s.%N) +DOWNTIME_START=0 +DOWNTIME_END=0 +IS_DOWN=false + +while true; do + # 현재 시각 (밀리초 단위 표시용) + NOW=$(date "+%H:%M:%S") + + # 요청 수행 (-s: 조용히, -m 1: 타임아웃 1초) + RESPONSE=$(curl -s -m 1 "$URL") + EXIT_CODE=$? + + # 2. 서버가 응답하지 않거나(다운됨) 에러인 경우 + if [ $EXIT_CODE -ne 0 ] || [ -z "$RESPONSE" ]; then + if [ "$IS_DOWN" = false ]; then + # 다운타임 시작 시간 기록 + DOWNTIME_START=$(date +%s.%N) + IS_DOWN=true + echo "[$NOW] 🔴 Service DOWN (Connection refused or Timeout)" + else + # 계속 다운 상태 + echo -ne "[$NOW] 🔴 Service DOWN...\r" + fi + + else + # 3. 응답이 성공한 경우 JSON 파싱 + NEW_VERSION=$(echo "$RESPONSE" | jq -r '.build.version') + + # 버전이 null이면 아직 부트 중이거나 데이터가 덜 로드된 상태 (잠재적 다운타임) + if [ "$NEW_VERSION" == "null" ]; then + if [ "$IS_DOWN" = false ]; then + DOWNTIME_START=$(date +%s.%N) + IS_DOWN=true + fi + echo "[$NOW] 🟡 Service UP but Version info missing..." + + # 4. 새 버전 감지! + elif [ "$NEW_VERSION" != "$OLD_VERSION" ]; then + # 다운타임이 있었다면 종료 시간 기록 + if [ "$IS_DOWN" = true ]; then + DOWNTIME_END=$(date +%s.%N) + fi + + echo "" + echo "-----------------------------------------------------" + echo "[$NOW] 🟢 NEW VERSION DETECTED!" + echo "Old Version: $OLD_VERSION" + echo "New Version: $NEW_VERSION" + + # 다운타임 계산 및 출력 + if [ "$IS_DOWN" = true ]; then + DURATION=$(echo "$DOWNTIME_END - $DOWNTIME_START" | bc) + printf "⏱️ Actual Downtime: %.3f seconds\n" "$DURATION" + else + echo "⏱️ Zero Downtime (No connection loss detected)" + fi + echo "-----------------------------------------------------" + break + + # 5. 여전히 구 버전인 경우 + else + if [ "$IS_DOWN" = true ]; then + # 다운되었다가 다시 구 버전이 뜬 경우 (재시작 실패 등) -> 다운타임 종료로 처리할지 결정 필요하나 여기선 리셋 + IS_DOWN=false + echo "[$NOW] 🟠 Recovered to OLD version ($OLD_VERSION)" + else + echo -ne "[$NOW] 🔵 Still Old Version ($OLD_VERSION)...\r" + fi + fi + fi + + sleep $SLEEP_SEC +done \ No newline at end of file