Spring/프로젝트

연차 신청, 관리 시스템 만들기 #13 logback.xml 설정, 로그 cloudwatch로 전달, 디스코드로 알람 설정

synclair 2024. 9. 20. 17:07

로컬 pc에선 에러가 나면 그냥 내가 그대로 고치면 된다.

하지만 ec2에 배포한 상황에서 로그 기록을 보려면

iterm 켜서 ec2에 ssh 접속 하고 docker logs [컨테이너이름] 하고

계속 이러다보니 현타가 와버렸다. 그리고 쓸데없는 INFO 레벨 로그도 내 귀찮음에 한 몫 했다.

그래서 서버에선 에러 로그만 출력되고 에러가 뜨면 CloudWatch에 저장되게 하고, 디스코드로 웹 훅을 걸어두기로 했따.

이전 회사에서도 이게 귀찮아서 slack에 알람 해뒀었는데 지금은 슬랙을 안쓰니.. 디스코드로 해보기로 했다.

    그래들
    // logback,cloudwatch
    implementation 'ca.pjer:logback-awslogs-appender:1.6.0'
    logback.xml
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <!-- 공통 설정 -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %clr(%5level) %cyan(%logger) - %msg%n" />
    <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %5level %logger - %msg%n" />

    <!-- 콘솔 출력 설정 (모든 프로파일에서 사용) -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <!-- prod 프로파일일 때만 적용 -->
    <springProfile name="prod">
        <!-- 디스코드 웹훅 설정 -->
        <springProperty name="DISCORD_WEBHOOK_URL" source="logging.discord.webhook-url"/>
        <appender name="DISCORD" class="com.github.napstr.logback.DiscordAppender">
            <webhookUri>${DISCORD_WEBHOOK_URL}</webhookUri>
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%d{HH:mm:ss} [%thread] [%-5level] %logger{36} - %msg%n```%ex{full}```</pattern>
            </layout>
            <username>ALERT</username>
            <tts>false</tts>
        </appender>

        <!-- 비동기 디스코드 알람 설정 -->
        <appender name="ASYNC_DISCORD" class="ch.qos.logback.classic.AsyncAppender">
            <appender-ref ref="DISCORD" />
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>ERROR</level>
            </filter>
        </appender>

        <!-- AWS CloudWatch 로그 설정 (prod) -->
        <springProperty name="AWS_ACCESS_KEY" source="cloud.aws.credentials.access-key"/>
        <springProperty name="AWS_SECRET_KEY" source="cloud.aws.credentials.secret-key"/>
        <appender name="aws_cloud_watch_log" class="ca.pjer.logback.AwsLogsAppender">
            <!-- ERROR 이상의 로그만 전송 -->
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>ERROR</level>
            </filter>
            <layout>
                <pattern>[%thread] [%date] [%level] [%file:%line] - %msg%n</pattern>
            </layout>
            <logGroupName>aws-error-log-prod/error-log</logGroupName>
            <logStreamUuidPrefix>error-log-prod-</logStreamUuidPrefix>
            <logRegion>ap-northeast-2</logRegion>
            <maxBatchLogEvents>50</maxBatchLogEvents>
            <maxFlushTimeMillis>30000</maxFlushTimeMillis>
            <maxBlockTimeMillis>5000</maxBlockTimeMillis>
            <retentionTimeDays>0</retentionTimeDays>
            <accessKeyId>${AWS_ACCESS_KEY}</accessKeyId>
            <secretAccessKey>${AWS_SECRET_KEY}</secretAccessKey>
            <encoder>
                <charset>UTF-8</charset>
                <pattern>%d{HH:mm:ss.SSS} [%thread] [%5level] %logger{35}[%method:%line] %m%n</pattern>
            </encoder>
        </appender>

        <!-- 에러 로거 (prod에서만 CloudWatch로 전송) -->
        <logger name="errorLogger" level="error" additivity="false">
            <appender-ref ref="aws_cloud_watch_log" />
        </logger>

        <!-- prod 환경에서만 DISCORD와 AWS CloudWatch 로그 전송 -->
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="ASYNC_DISCORD" />
            <appender-ref ref="aws_cloud_watch_log" />
        </root>
    </springProfile>

    <!-- 다른 프로파일에 대한 루트 로거 (예: local, dev) -->
    <springProfile name="!prod">
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
        </root>
    </springProfile>
</configuration>

에러 발생 시 디스코드로 알람이 잘 왔다.

보아하니 Github Actions에 이사간 RDS 주소 최신화를 안해서 디비 연결이 안되서 저러는 것 같다.

클라우드와치에서도 로그가 잘 출력 된다.

역시 사람은 귀찮음에서 영감을 얻는 것 같다..

cloudwatch 참고: https://devlog-wjdrbs96.tistory.com/329

 

 

PS.
xml 중간에 aws 계정 액세스키, 비밀키 설정을 yml에서 불러온다.

저렇게 설정 해두고 분명 내가 application-local.yml 을 .gitignore에 설정 해두었는데

깃허브에 application-local.yml이 업로드 되버렸다; 지우다가 깃이 꼬여서 뭔 삽질을 했는지 참..

이미 한번 깃에 올라간 것은 .gittgnore에 설정해도 의미가 없다는 것을 알았다. 그래서 application-local.yml 깃 내에 캐시를 지우는 법을 알아냈다.

git rm  --cached application-local.yml

 

지우고 새로 유저 발급을 했다.

aws 관련 키를 푸시해두고 크게 인생 경험 당한 썰들이 참 많으니 조심 해야한다..

https://www.youtube.com/shorts/6jbcpw3YJ4c