JiYoung Dev πŸ–₯

둜그 레벨 및 둜그 μž‘μ„± κΈ°μ€€ λ³Έλ¬Έ

Study/Back-End

둜그 레벨 및 둜그 μž‘μ„± κΈ°μ€€

Shinjio 2024. 11. 11. 21:02
λ°˜μ‘ν˜•

μš΄μ˜μ€‘μΈ μ†”λ£¨μ…˜μ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•΄ 원인을 νŒŒμ•…ν•˜λ €λŠ”λ°, μ—λŸ¬λ₯Ό μ œμ™Έν•œ debugλ‚˜ info λ‘œκ·Έκ°€ ν•˜λ‚˜λ„ μ°νžˆμ§€ μ•Šμ•„ 원인을 νŒŒμ•…ν•  수 μ—†λŠ” 일이 λ°œμƒν•˜μ˜€λ‹€. κ·Έλž˜μ„œ μ΄λ²ˆμ— 둜그 μ°λŠ” μ†ŒμŠ€λ₯Ό μΆ”κ°€ν•΄ 패치λ₯Ό ν•˜κ²Œ λ˜μ—ˆλŠ”λ° μ–΄λ–»κ²Œ 둜그λ₯Ό 찍어야 μš΄μ˜ν•  λ•Œ μƒνƒœλ₯Ό 잘 λͺ¨λ‹ˆν„°λ§ ν•  수 μžˆμ„μ§€ κ³ λ―Όν•˜κ²Œ λ˜μ—ˆκ³ , 이번 글을 μž‘μ„±ν•˜κ²Œ λ˜μ—ˆλ‹€.


πŸ“– 둜그(Log)의 λͺ©μ 

λ‘œκ·ΈλŠ” μ‹œμŠ€ν…œμ΄λ‚˜ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ λ°œμƒν•˜λŠ” λͺ¨λ“  이벀트의 기둝으둜, κ°œλ°œμžμ™€ 운영 νŒ€μ΄ μ‹œμŠ€ν…œμ˜ μ„±λŠ₯을 λΆ„μ„ν•˜κ³  문제λ₯Ό ν•΄κ²°ν•˜λŠ” 데 μ€‘μš”ν•œ 정보λ₯Ό μ œκ³΅ν•œλ‹€.

  • μ„œλΉ„μŠ€ λ™μž‘ μƒνƒœ νŒŒμ•…
  • μž₯μ•  νŒŒμ•… 및 μ•Œλ¦Ό
  • 둜그 뢄석을 ν†΅ν•œ μ„œλΉ„μŠ€ μ§€ν‘œμ˜ 확인, νŠΈλžœμž­μ…˜, μ„±λŠ₯ νŒŒμ•…

ν•˜μ§€λ§Œ λŒ€κ·œλͺ¨ μ‹œμŠ€ν…œμ—μ„œλŠ” 맀일 μˆ˜μ‹­ GB에 λ‹¬ν•˜λŠ” 둜그 데이터가 생성될 수 μžˆμ–΄ 이λ₯Ό 효율적으둜 κ΄€λ¦¬ν•˜μ§€ μ•ŠμœΌλ©΄ μ€‘μš”ν•œ 정보λ₯Ό λ†“μΉ˜κ±°λ‚˜ 문제 해결에 ν•„μš”ν•œ μ‹œκ°„μ΄ κΈΈμ–΄μ§ˆ 수 μžˆλ‹€.

λ”°λΌμ„œ 둜그λ₯Ό 생성할 λ•Œμ—λŠ” κΌ­ ν•„μš”ν•œ λ‘œκ·ΈμΈμ§€ ν™•μΈν•˜κ³ , μ‹œμŠ€ν…œ μƒνƒœ νŒŒμ•…μ„ μœ„ν•΄ λ†“μΉ˜λŠ” 뢀뢄은 μ—†λŠ”μ§€ 생각해가며 생성해야 ν•œλ‹€.

 

πŸ“– 둜그 레벨(Log Level)

둜그 λ ˆλ²¨μ€ 둜그 λ©”μ‹œμ§€μ˜ μ€‘μš”λ„λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μˆ˜μ€€μœΌλ‘œ ALLμ—μ„œ OFFλ₯Ό ν¬ν•¨ν•˜μ—¬ 8개의 레벨이 μžˆλ‹€. ν•˜μ§€λ§Œ 보톡은 ALL, OFFλ₯Ό μ œμ™Έν•œ 6단계λ₯Ό 이야기 ν•œλ‹€.

  • TRACE
    • κ°€μž₯ μƒμ„Έν•œ 둜그 레벨둜, μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ‹€ν–‰ 흐름과 디버깅 정보λ₯Ό μƒμ„Ένžˆ κΈ°λ‘ν•œλ‹€. 주둜 디버깅 μ‹œ μ‚¬μš©ν•œλ‹€.
  • DEBUG
    • 디버깅 λͺ©μ μœΌλ‘œ μ‚¬μš©λ˜λ©°, 개발 λ‹¨κ³„μ—μ„œ μƒμ„Έν•œ 정보λ₯Ό κΈ°λ‘ν•œλ‹€.
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λ‚΄λΆ€ λ™μž‘μ„ μ΄ν•΄ν•˜κ³  문제λ₯Ό λΆ„μ„ν•˜λŠ” 데 도움을 μ€€λ‹€.
  • INFO
    • 정보성 λ©”μ‹œμ§€λ₯Ό κΈ°λ‘ν•œλ‹€.
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ£Όμš” μ΄λ²€νŠΈλ‚˜ μ‹€ν–‰ μƒνƒœμ— λŒ€ν•œ 정보λ₯Ό μ „λ‹¬ν•œλ‹€.
  • WARN
    • κ²½κ³ μ„± λ©”μ‹œμ§€λ₯Ό κΈ°λ‘ν•œλ‹€.
    • μ˜ˆμƒμΉ˜ λͺ»ν•œ λ¬Έμ œλ‚˜ 잠재적인 였λ₯˜ 상황을 μ•Œλ¦¬λŠ” λ©”μ‹œμ§€μ΄λ‹€.
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ •μƒμ μœΌλ‘œ λ™μž‘ν•˜μ§€λ§Œ μ£Όμ˜κ°€ ν•„μš”ν•œ 상황을 μ•Œλ €μ€€λ‹€.
  • ERROR
    • 였λ₯˜ λ©”μ‹œμ§€λ₯Ό κΈ°λ‘ν•œλ‹€.
    • μ‹¬κ°ν•œ 문제 λ˜λŠ” μ˜ˆμ™Έ 상황을 λ‚˜νƒ€λ‚΄λ©°, μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 정상적인 λ™μž‘μ— 영ν–₯을 λ―ΈμΉ  수 μžˆλŠ” 문제λ₯Ό μ•Œλ¦°λ‹€.
  • FETAL
    • κ°€μž₯ μ‹¬κ°ν•œ 였λ₯˜ λ©”μ‹œμ§€λ₯Ό κΈ°λ‘ν•œλ‹€.
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λ™μž‘μ„ μ€‘λ‹¨μ‹œν‚¬ 수 μžˆλŠ” 치λͺ…적인 였λ₯˜λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
    • 일반적으둜 μ΄λŸ¬ν•œ 였λ₯˜λŠ” 볡ꡬ가 λΆˆκ°€λŠ₯ν•˜κ±°λ‚˜ 맀우 μ–΄λ €μš΄ 상황을 μ˜λ―Έν•œλ‹€.

 

πŸ”Ž MVC νŒ¨ν„΄μ—μ„œμ˜ 둜그 적용

μœ„μ—μ„œ 각 둜그 λ ˆλ²¨μ— λŒ€ν•΄ μ•Œμ•„λ³΄μ•˜λŠ”λ°, μ‹€μ œλ‘œλŠ” μ–΄λ–»κ²Œ μ μš©ν•΄μ•Ό ν•˜λŠ”μ§€ 와닿지 μ•Šμ•˜λ‹€. λ”°λΌμ„œ ν˜„μž¬ 운영 μ„œλ²„μ— 적용된 λ””μžμΈ νŒ¨ν„΄μΈ MVC νŒ¨ν„΄μ—μ„œ 각 κ³„μΈ΅λ³„λ‘œ μ–΄λ–»κ²Œ 둜그λ₯Ό μ μš©ν•˜λŠ” 것이 쒋을지 μ•Œμ•„λ³΄μ•˜λ‹€.

 

1. Controller 계측

  • INFO: 각 μš”μ²­μ˜ μ‹œμž‘κ³Ό 끝에 λŒ€ν•œ 둜그λ₯Ό κΈ°λ‘ν•˜λŠ” 것이 μœ μš©ν•¨
  • WARN: μž…λ ₯ 값이 μ˜ˆμƒ λ²”μœ„λ₯Ό 벗어났을 λ•Œ ν˜Ήμ€ κΆŒν•œμ΄ λΆ€μ‘±ν•œ 경우
  • ERROR: μ‹€μ œ 였λ₯˜κ°€ λ°œμƒν–ˆμ„ λ•Œ
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
public class UserController {
    private static final Logger logger = LogManager.getLogger(UserController.class);
    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        logger.info("User request received for ID: {}", id);
        try {
            User user = userService.getUserById(id);
            logger.info("User retrieved successfully for ID: {}", id);
            return ResponseEntity.ok(user);
        } catch (UserNotFoundException e) {
            logger.warn("User not found for ID: {}", id);
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
        } catch (Exception e) {
            logger.error("An error occurred while retrieving user for ID: {}. Error: {}", id, e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }
}

 

2. Service 계측

  • DEBUG: νŠΉμ • 쑰건을 λ§Œμ‘±ν–ˆμ„ λ•Œ λΆ„κΈ°λ˜λŠ” λ‘œμ§μ΄λ‚˜ λ³΅μž‘ν•œ 연산을 μˆ˜ν–‰ν•  λ•Œ 쀑간 κ²°κ³Ό 기둝
  • INFO: λΉ„μ¦ˆλ‹ˆμŠ€ ν”„λ‘œμ„ΈμŠ€ μ™„λ£Œμ‹œ(ex. νšŒμ›κ°€μž… μ™„λ£Œ, μ£Όλ¬Έ 생성 μ™„λ£Œ λ“±)
  • WARN: 잠재적 문제 상황
  • ERROR: μ˜ˆμ™Έ λ°œμƒμ‹œ
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    private static final Logger logger = LogManager.getLogger(UserService.class);
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User getUserById(Long id) throws UserNotFoundException {
        logger.debug("Looking up user with ID: {}", id);
        User user = userRepository.findById(id).orElseThrow(() -> {
            logger.warn("User with ID {} not found in the database.", id);
            return new UserNotFoundException("User not found");
        });
        logger.info("User found: {}", user.getUsername());
        return user;
    }
}

 

3. Repository 계측

  • TRACE: λ°μ΄ν„°λ² μ΄μŠ€ 쿼리와 κ΄€λ ¨λœ 상세 정보 기둝할 λ•Œ
  • DEBUG: 쿼리 μ‹€ν–‰ κ²°κ³Ό ν˜Ήμ€ λ°μ΄ν„°λ² μ΄μŠ€μ™€μ˜ μƒν˜Έμž‘μš© 기둝
  • ERROR: λ°μ΄ν„°λ² μ΄μŠ€μ™€μ˜ μƒν˜Έμž‘μš©μ—μ„œ μ‹€μ œ μ—λŸ¬κ°€ λ°œμƒν•œ 경우
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

public class UserRepositoryImpl {
    private static final Logger logger = LogManager.getLogger(UserRepositoryImpl.class);

    public User findUserById(Long id) {
        try {
            logger.trace("Executing SQL query to find user with ID: {}", id);
            User user = findById(id); // Assume findById is implemented to get User from DB
            logger.debug("User data retrieved from database: {}", user);
            return user;
        } catch (Exception e) {
            logger.error("Database error while fetching user with ID: {}. Error: {}", id, e.getMessage());
            throw e;
        }
    }
}

 

πŸ“– 참고자료

https://velog.io/@ykh9759/%EB%A1%9C%EA%B7%B8-%EB%A0%88%EB%B2%A8Logging-Level

 

둜그 레벨(Logging Level)

둜그 λ ˆλ²¨μ— 따라 ν•„μš”ν•œ 둜그λ₯Ό 확인할 수 μžˆλ‹€.λ‘œκΉ… λ ˆλ²¨μ€ ALLκ³Ό OFFλ₯Ό ν¬ν•¨ν•˜λ©΄ 8개 μ΄μ§€λ§Œ 보톡 ALLκ³Ό OFFλ₯Ό μ œμ™Έν•œ 6단계λ₯Ό μ΄μ•ΌκΈ°ν•œλ‹€.ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFFALL: κ°€μž₯ 상세

velog.io

https://developsd.tistory.com/132

 

Log λ‘œκ·ΈλŠ” μ™œ μ‚¬μš©ν•˜λŠ” 것인가? 둜그 레벨 정리

Log λ‘œκ·ΈλŠ” μ™œ μ λŠ” 것인가? 둜그λ₯Ό μ λŠ” 경우 둜그 μž‘μ„± λͺ©μ κ³Ό μš”κ΅¬μ‚¬ν•­μ— λŒ€ν•œ νŒŒμ•…μ΄ μš°μ„  ν•„μš”ν•˜λ‹€. μ†ŒμŠ€ μ½”λ“œμ— 둜그λ₯Ό 많이 적게 되면 였히렀 μš΄μ˜ν•˜λ©΄μ„œ λ§Žμ€ 둜그둜 인해 디버깅이 더 뢈

developsd.tistory.com

https://chatgpt.com/

 

λ°˜μ‘ν˜•