Logbook 으로 access log 남기기

2024. 1. 4. 10:23·개발/java

Access Log를 남겨보자.

환경은 다음과 같다.

  • jdk 11.0.21
  • springboot 2.7.18

먼저 pom 에 dependency 추가 한다.  - 작성일 기준 2.x 마지막 버전 2.16.0 으로 진행

<!-- pom.xml -->
<dependency>
    <groupId>org.zalando</groupId>
    <artifactId>logbook-spring-boot-starter</artifactId>
    <version>2.16.0</version>
</dependency>

 

logback에도 관련 설정을 추가해 본다.

<!-- logback-spring.xml -->
    <!-- Console Appenders -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${LOGS_CONSOLE_PATTERN}</pattern>
        </encoder>
    </appender>


    <!-- Access Log Appenders -->
    <appender name="ACCESS_FILE_ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS_ABSOLUTE_PATH}/${LOGS_FILE_NAME}-access.log</file>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <encoder>
            <pattern>${LOGS_FILE_PATTERN}</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOGS_ABSOLUTE_PATH}/${LOGS_FILE_NAME}-access.%d{yyyy-MM-dd}.%i.log</fileNamePattern>      
            <timeBasedFileNamingAndTriggeringPolicy  class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
               <!-- or whenever the file size reaches 100MB -->
               <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>
    </appender>

    <!-- Access Loggers -->
    <logger name="com.dev.log.common.log.AccessLogWriter" level="INFO" additivity="false">
        <appender-ref ref="STDOUT" /> <!-- 파일 appender는 필요시 아래에 추가 -->
    </logger>

 

application.yml에서 log 관련 설정을 추가한다. 

access log 를 TRACE로 찍고 있으니 제외시킬 exclude 대상을 지정해준다.

logging:
  config: classpath:logback-spring.xml
  
#log path
logs:
  absolute:
    path: C:/dev/log
  level:
    root: INFO
    com: DEBUG
  name: fullmooney-tistory-com

logbook:
  exclude:
  - '**/health'
  - '**/v3/api-docs/**'
  - '**/v2/api-docs/**'
  - '**/v1/api-docs/**'
  - '**/swagger-resources/**'
  - '**/configuration/security'
  - '**/swagger'
  - '**/csrf'
  - '**/error'
  - '**/configuration'
  - '**/swagger-ui.html'
  - '**/favicon.*'
  - '**/h2-console/**'
  - '**/webjars/**'
  - '**/swagger-ui/**'
  - '**/swagger-ui/*'
  - '**/swagger-resources/**'
  - '**/etrack/exportArchive'
  - '**/*-stream'

 

HttpLogWriter 인터페이스를 구현하는 AccessLogWriter 컴포넌트를 추가한다.

import java.io.IOException;

import org.springframework.stereotype.Component;
import org.zalando.logbook.Correlation;
import org.zalando.logbook.HttpLogWriter;
import org.zalando.logbook.Precorrelation;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class AccessLogWriter implements HttpLogWriter  {

  @Override
  public void write(Precorrelation precorrelation, String request) throws IOException {
    if(log.isInfoEnabled()) {
      log.info("############################ request: {}", request);
    }
  }

  @Override
  public void write(Correlation correlation, String response) throws IOException {
    if(log.isInfoEnabled()) {
      log.info("############################ response: {}", response);
    }
  }
}

 

 

이제 api 를 추가하고 swagger를 통해 테스트 해보자.

import java.util.ArrayList;
import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.dev.log.domain.SampleVO;

@RestController
@RequestMapping("/api/logbook")
public class LogbookTestController {
    
    @PostMapping("/logging-access-log")
    public ResponseEntity<List<SampleVO>> postMethodName(@RequestBody SampleVO vo) {
        
        List<SampleVO> listVO = new ArrayList<>();
        
        SampleVO tot = new SampleVO();
        tot.setLeague("PL");
        tot.setTeam("TOT");
        tot.setName("Son Heung-min");
        tot.setNumber(7);

        listVO.add(tot);
        listVO.add(vo);


        return ResponseEntity.ok(listVO);
    }
    
}

 

swagger 실행 결과는 다음과 같이 정상으로 수행되었다.

 

console 출력에도 request와 response가 잘 출력되었다. 

글씨가 작아 다시 옮겨보면..

20240104 10:11:42.449 [http-nio-8080-exec-5] INFO c.d.log.common.log.AccessLogWriter [19]-[fullmooney-tistory-com,59e6c3acd97c298a]-############################ request: {"origin":"remote","type":"request","correlation":"c7626b8e22728fa2","protocol":"HTTP/1.1","remote":"0:0:0:0:0:0:0:1","method":"POST","uri":"http://localhost:8080/api/logbook/logging-access-log","host":"localhost","path":"/api/logbook/logging-access-log","scheme":"http","port":"8080","headers":{"accept":["*/*"],"accept-encoding":["gzip, deflate, br"],"accept-language":["ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7"],"connection":["keep-alive"],"content-length":["94"],"content-type":["application/json"],"cookie":["JSESSIONID=7F79E354F3E2D29A2509BF09D7FABE59"],"host":["localhost:8080"],"origin":["http://localhost:8080"],"referer":["http://localhost:8080/swagger-ui/index.html"],"sec-ch-ua":["\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\""],"sec-ch-ua-mobile":["?0"],"sec-ch-ua-platform":["\"Windows\""],"sec-fetch-dest":["empty"],"sec-fetch-mode":["cors"],"sec-fetch-site":["same-origin"],"user-agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"]},"body":{"league":"Ligue1","team":"PSG","name":"Lee Gang-in","number":0,"wage":0}}
20240104 10:11:42.469 [http-nio-8080-exec-5] INFO c.d.log.common.log.AccessLogWriter [26]-[fullmooney-tistory-com,59e6c3acd97c298a]-############################ response: {"origin":"local","type":"response","correlation":"c7626b8e22728fa2","duration":28,"protocol":"HTTP/1.1","status":200,"headers":{"Connection":["keep-alive"],"Content-Type":["application/json"],"Date":["Thu, 04 Jan 2024 01:11:42 GMT"],"Keep-Alive":["timeout=60"],"Transfer-Encoding":["chunked"]},"body":[{"league":"PL","team":"TOT","name":"Son Heung-min","number":7,"wage":0},{"league":"Ligue1","team":"PSG","name":"Lee Gang-in","number":0,"wage":0}]}

 

Git: tistory/log at e4bf956766416f11a03e6d818d2d10c92212d0f7 · FullMooney/tistory (github.com)

 

728x90

'개발 > java' 카테고리의 다른 글

springboot + redis @Cacheable 사용  (3) 2024.01.11
springboot redis client 만들기  (1) 2024.01.08
mybatis interceptor 암복호화 처리  (1) 2023.12.13
JPA EntityListener로 multi JpaRepository save  (1) 2022.09.07
Runtime에서 annotation attribute 변경 - influxDB @Measurement 공통 DTO 만들기  (1) 2022.09.07
'개발/java' 카테고리의 다른 글
  • springboot + redis @Cacheable 사용
  • springboot redis client 만들기
  • mybatis interceptor 암복호화 처리
  • JPA EntityListener로 multi JpaRepository save
yunapapa
yunapapa
working on the cloud
    250x250
  • yunapapa
    supermoon
    yunapapa
  • 전체
    오늘
    어제
    • 분류 전체보기 (94)
      • 개발 (20)
        • java (17)
        • web (2)
        • MSX (1)
        • Go (0)
      • CloudNative (50)
        • App Definition & Developeme.. (17)
        • Orchestration & Management (4)
        • Runtime (3)
        • Provisioning (7)
        • Observability & Analysis (14)
        • event review (5)
      • AWS (7)
      • 환경관련 (17)
      • 취미생활 (0)
        • 맛집 (0)
        • 게임 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • CNCF Past Events
    • Kubernetes Korea Group
  • 공지사항

  • 인기 글

  • 태그

    istio
    AWS
    gitlab
    티스토리챌린지
    springboot
    dop-c02
    Java
    devops
    Pinpoint
    helm
    OpenShift
    k8s
    kubernetes
    APM
    오블완
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
yunapapa
Logbook 으로 access log 남기기
상단으로

티스토리툴바