log 메시지는 언제 쓸까
string뿐만 아니라 custom data도 포함 가능. 읽기
Swift에서는 Logger 구조체를 만들고, 메소드를 사용한다. (Objective-C에서는 OSLog)
이슈를 진단할 때, 너무 많은 로그 메시지를 피하기 위해, log 객체를 만들 때 두 가지의 커스텀 스트링을 써서 연관없는 메시지들을 필터한다. 필터할 필요가 없다면, Logger와 OSLog는 기본 로그를 제공하고, 특정 하위 시스템(subsystem)과 카테고리를 요구하지 않는 메세지를 기록하는데 사용할 수 있다.
하위 시스템 문자열(subsystem string)은 앱 이나 앱 내에서 넓은 기능 영역을 식별한다. 앱이 프로세스를 만든다면 이를 com.example.myapp와 같이 reverse-DNS notaion을 사용해서 다양한 하위 시스템 문자열을 사용할 수 있다.
category string은 주어진 subsystem에서 특정한 컴포넌트나 모듈을 식별한다. 예를 들면 유저 인터페이스, 데이터 모델, 네트워킹 코드 등을 정의할 수 있다.
특정 메시지에 대해 얼마나 심각한지, 중요성을 정의. 이 레벨은 시스템이 메시지를 어떻게 처리할지 결정한다.(처음에 모든 메시지를 메모리에 저장하고, 보다 심각한 로그 레벨은 디스크에 저장 )
Debug -> Info -> Notice -> Fault (오른쪽으로 갈수록 중요. 저장여부, 조건 다름)
레벨이 높은 경우 디스크에 저장하기 때문에 오버헤드가 발생하며, 시스템이 정보를 로그하는 속도에 영향을 준다.(Debug는 메모리에만 저장되기 때문에 오버헤드가 매우 낮다)
버전이 낮은 macOS는 os_log 메소드, OSLog 객체를 파라미터로 받는 메소드를 사용한다.
Logger를 사용하는 경우, OSLog를 import해주자
if #available(OSX 11.0, *) {
// default 로그 레벨로 기본 Logger 객체 사용
let defaultLog = Logger()
defaultLog.log("This is a default message.")
// debug 로그 레벨로 기본 Logger 객체 사용
defaultLog.debug("This is a debug message.")
// error 로그 레벨로 커스텀 Logger 객체 사용
let customLog = Logger(subsystem: "com.your_company.your_subsystem",
category: "your_category_name")
customLog.error("An error occurred!")
} else {
// 버전이 낮은 경우를 위해 사용
os_log("This is a default message.")
os_log("This is a debug message.", log: OSLog.default, type: .debug)
let customLog = OSLog(subsystem: "com.your_company.your_subsystem",
category: "your_category_name")
os_log("An error occurred!", log: customLog, type: .error)
}
Swift는 문자열 보간법을 사용(ex. (variableName))
Objective-C는 format string specifiers를 사용한다.(ex. %@, %d)
보다 읽기 쉽게, 문자열 보간법을 사용한 값을 custom하게 formatting할 수 있다. 십진수의 수로 바꾸거나, 글자 길이를 한정하거나, 불리언 값을 yes/no 문자열로 바꾸거나, 유동소수점 숫자의 precision을 정해줄 수 있다.
privacy option을 사용하여 메시지에서 값을 숨기거나 보여줄 수 있다.
let userAge : Int = getUserAge()
// Hide the user’s age.
Logger().info("User's age: \(userAge, privacy: .private)"`
// 다시 보이게 하려면 public으로 설정
Logger().info("Smoothie name: \(smoothieName, privacy: .public)")
값을 식별하기 위해 privacy를 지키면서 hash값을 주는 것도 가능하다.
Logger().info("Start transaction for account \(accountNumber,
privacy: .private(mask: .hash))")