[Swift] 통합 로깅 시스템으로 로깅 해보자!: OSLog

Ryan (Geonhee) Son·2021년 5월 2일
4

Study Stack

목록 보기
17/34

여느 때처럼 즐겁게 코드를 작성하던 찰나, 진행하던 프로젝트의 PR에 대한 피드백 (코드 리뷰)을 받았습니다.

이미지에서 피드백해주신 코드는 옵셔널 바인딩 결과에 따라 에러를 debugPrint 해주는 부분이었는데요, 과연 링크를 남겨주신 부분이 무엇일까 클릭해보았더니 Zedd님께서 os_log를 주제로 작성하신 글이었습니다. 요지는 Unified logging System (통합 로깅 시스템)에 메시지를 로깅할 수 있는 방식이라는 것이네요. 제 나름대로 내용을 공부해 가볼게요.


공식문서가 설명하는 OSLog

OSLog (프레임워크)
과거의 데이터를 읽기 위한 통합 로깅 시스템.
OSLog 프레임워크는 사용자 (프로그래머)가 로그를 읽을 수 있게 해준다. 통합 로깅 시스템을 사용하면 Instrument 및 Console과 같은 Apple 툴과 함께 사용할 사용자 지정 디버깅 및 분석 툴을 구축할 수 있게 해준다.

오케이, 링크된 Logging을 살펴봅시다.

Logging
통합 로깅 시스템을 사용하여 디버깅 및 성능 분석을 위해 앱에서 원격 측정 (telemetry)을 캡처한다.

아직 통합 로깅 시스템에 대한 이해는 하지 못했지만 제가 기존에 에러가 일어나면 print를 해서 콘솔창으로 확인하던 방식과 달리 로그를 남길 수 있는 방법인가 보네요. 계속 읽다보니 문서에 중요한 내용이 있었습니다.

통합 로깅 시스템은 시스템의 모든 수준에서 원격 측정을 캡처할 수 있는 포괄적이고 성능이 뛰어난 API를 제공합니다. 이 시스템은 데이터를 텍스트 기반 로그 파일에 쓰지 않고 메모리 및 디스크에 로그 데이터를 중앙 집중식으로 저장합니다. 콘솔 앱, 로그 명령줄 도구 또는 Xcode 디버그 콘솔을 사용하여 로그 메시지를 보거나 OSLog 프레임워크를 사용하여 로그 메시지에 프로그래밍 방식으로 액세스할 수도 있습니다.

그렇군요. 성능이 좋고 모든 수준에서 사용할 수 있다. 모든 수준에 대해 궁금하신 분은 이 문서를 읽어보세요. 아래와 같은 표를 찾으실 수 있으실 것입니다.

수준에 대해 간단하게 보자면 아래와 같습니다.

  • Debug: 개발 중 코드 디버깅 시 사용할 수 있는 유용한 정보
  • Info: 문제 해결 (트러블슈팅) 시 활용할 수 있는, 도움이 되지만 필수적이지 않은 정보
  • Notice (기본값): 문제 해결에 필수적인 정보. Failure를 초래할 수 있는 정보
  • Error: 코드 실행 중 나타난 에러. 활동 객체가 존재하는 경우 관련 프로세스 체인에 대한 정보 캡처
  • Fault: 코드 속의 폴트 (Faults) 및 버그 관련 정보. 활동 객체가 존재하는 경우 관련 프로세스 체인에 대한 정보 캡처

제약사항

또 한가지 중요한 점은 통합 로깅 시스템이 iOS 10, macOS 10.12, tvOS 10.0, watchOS 3.0 이후 버전부터 지원한다는 점입니다.

메서드별 에러 발생에 대한 로깅 방식 확인

준비해둔 에러 상황에서 어떻게 작동하는지 확인해보겠습니다. mac에 기본 탑재된 console 앱으로 확인해볼게요.

  1. os_log(_:)
import OSLog

os_log("artWork is nil.")

  1. os_log(_:log:_:)
os_log(.error, log: .default, "artwork is Nil.")
os_log(.fault, log: .default, "artwork is Nil.")

물론 콘솔에서도 아래와 같이 로깅된 내용을 확인할 수 있습니다.

더 강력하게 OSLog를 활용하는 방법

아래와 같이 OSLog 클래스의 인스턴스를 OSLog 프레임워크에 타입 프로퍼티로 만들어 확장해주시면 원하시는 subsystem과 카테고리로 메시지를 로깅하실 수 있습니다.

import OSLog

extension OSLog {
  private static var subsystem = Bundle.main.bundleIdentifier!
  static let ui = OSLog(subsystem: subsystem, category: "UI")
  static let data = OSLog(subsystem: subsystem, category: "Data")
}

// 메시지 로깅이 필요한 위치에서 아래 메서드를 호출
os_log(.fault, log: .data, OSLogMessage.artworkIsNil)

StaticString 타입의 장벽에 부딪힌 당신에게

메시지 타입으로 StaticString을 요구하여 문자열 보간법과 같은 방법을 직접적으로 적용할 수는 없지만 아래와 같은 방법으로 우회적으로 적용할 수 있습니다. 참고 자료

// 아래는 메시지가 `StaticString` 타입이 아니므로 에러가 발생합니다. 
os_log(.info, log: .network, "New used logged in with name \(user.name)") // 에러 발생!

// 메시지를 미리 선언하여 아래와 같이 우회적으로 사용할 수 있습니다.
let message = "New used logged in with name \(user.name)"
os_log(.info, log: .network, "%@", message)

읽어주셔서 감사합니다!

참고자료

profile
합리적인 해법 찾기를 좋아합니다.

0개의 댓글