Spring Boot : Logger 사용 기본 절차 및 레벨 설정
0. 스프링에서 로거를 사용하기 위해서 Sl4j를 사용한다.
1. Sl4j는 Log4j와 Logback을 Wrapping하여 간단한 사용환경을 제공한다.
1-1 로깅 단계는 Error, Warn, Info, Debug, Trace로 구분된다.
1-2 하위의 단계는 상위의 단계의 로그를 포함하여 출력한다.
1-3 레벨의 세팅은 LOGGER.setLevel(INFO); 이런 형식으로 지정할 수 있다.
2. Spring Starter 모듈에는 기본적으로 log4j와 logback이 포함되어 별도의 dependecy추가는 필요없다.
2-1 기본 구현 라이브러리가 Logback이고 원하면 Log4j로 교체할 수 있다.
2-2 Log4j를 위해서는 추가 dependency설정이 필요하다.
3. 사용방법은
3-1 로거를 static final로 정의하고 클래스를 지정한다.
3-2 로깅하는 데이터를 5가지 로깅 레벨 중 원하는 레벨에 맞추어 설정한다.
package pe.pilseong.flightreservation.controllers;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import pe.pilseong.flightreservation.entities.Flight;
import pe.pilseong.flightreservation.repositories.FlightRepository;
@Controller
public class FlightController {
@Autowired
FlightRepository flightRepository;
private static final Logger LOGGER = LoggerFactory.getLogger(FlightController.class);
@PostMapping("/findFlights")
public String findFlights(
@RequestParam String from,
@RequestParam String to,
@RequestParam("departureDate") @DateTimeFormat(pattern = "MM-dd-yyyy") Date departureDate,
Model model) {
LOGGER.info("Inside findFlights() from:: " + from +
", to:: " + to + ", departureDate:: " + departureDate.toString());
List<Flight> flights = this.flightRepository.findFlights(from, to, departureDate);
model.addAttribute("flights", flights);
LOGGER.info("Inside findFlights() fligts are " + flights.toString());
return "displayFlights";
}
}
4. 루트 로거의 레벨을 지정하는 방법은 application.properties에 지정하면 된다.
4-1 기본 레벨은 Info로 설정되어 있다.
4-2 레벨 변경은 아래처럼 원하는 레벨을 설정한다.
logging.level.root=ERROR
5. 간단하게 로거를 사용하기를 원하면 lombok의 @Slf4j를 사용할 수 있다.
5-1 아래코드를 보면 클래스에 @Slf4j가 지정되어 있는데, 이것은 자동으로 logger 설정을 해준다.
5-1-1 바로 아래 붙인 LOGGER를 생성해 주는 구문과 동일하다. 변수이름만 log로 다를 뿐이다.
private static final Logger LOGGER = LoggerFactory.getLogger(FlightController.class);
5-2 메소드를 보면 log.info 같은 형식으로 출력이 가능한 것을 볼 수 있다. 아주 편리하다.
package pe.pilseong.employees.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.extern.slf4j.Slf4j;
import pe.pilseong.employees.model.Employee;
import pe.pilseong.employees.serivce.EmployeeService;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Slf4j
@RestController
@RequestMapping("/employees")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@PostMapping
public Mono<ResponseEntity<Employee>> createEmployee(@RequestBody Employee employee) {
return this.employeeService.save(employee)
.map(savedEmployee-> new ResponseEntity<>(savedEmployee, HttpStatus.CREATED))
.defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
@GetMapping
public Flux<Employee> findAll() {
log.info("findAll in EmployeeController");
return this.employeeService.findAll();
}
@GetMapping("/{id}")
public Mono<ResponseEntity<Employee>> findOne(@PathVariable String id) {
log.info("find one in EmployeeController id :: " + id);
return this.employeeService.findOne(id)
.map(fetchedEmployee-> new ResponseEntity<>(fetchedEmployee, HttpStatus.OK))
.defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
@PutMapping("/{id}")
public Mono<ResponseEntity<Employee>> update(@PathVariable String id, @RequestBody Employee employee) {
return this.employeeService.update(id, employee)
.map(savedEmployee-> new ResponseEntity<>(savedEmployee, HttpStatus.CREATED))
.defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
@DeleteMapping("/{id}")
public Mono<Void> delete(@PathVariable String id) {
return this.employeeService.delete(id);
}
}