はじめに
こんにちは。iOSアプリ開発グループの神山です。
開発時にログを出したい際に、
print()を使用したり、SwiftBeaverなどのライブラリを使用したり様々な方法があると思います。
今回はiOS14以降で使用できるLoggerも含めて、OSLogを使ってログを出力する方法をご紹介したいと思います。
OSLogでのログ出力
ログを出力する際には
os_logを使いやすいように拡張して、以下のようなものを作成していました。
import OSLog
extension OSLog {
static let ui = OSLog(subsystem: "com.sample", category: "UI")
static let api = OSLog(subsystem: "com.sample", category: "API")
static let other = OSLog(subsystem: "com.sample", category: "OTHER")
}
extension OSLogType: CustomStringConvertible {
public var description: String {
switch self {
case .info:
return "INFO"
case .debug:
return "DEBUG"
case .error:
return "ERROR"
case .fault:
return "FAULT"
default:
return "DEFAULT"
}
}
}
struct Logger {
static func info(
osLog: OSLog = .default,
message: String,
file: String = #file,
function: String = #function,
line: Int = #line
) {
doLog(
message: message,
osLog: osLog,
logType: .info,
file: file,
function: function,
line: line
)
}
static func debug(
osLog: OSLog = .default,
message: String,
file: String = #file,
function: String = #function,
line: Int = #line
) {
doLog(
message: message,
osLog: osLog,
logType: .debug,
file: file,
function: function,
line: line
)
}
static func error(
osLog: OSLog = .default,
message: String,
file: String = #file,
function: String = #function,
line: Int = #line
) {
doLog(
message: message,
osLog: osLog,
logType: .error,
file: file,
function: function,
line: line
)
}
static func fault(
osLog: OSLog = .default,
message: String,
file: String = #file,
function: String = #function,
line: Int = #line
) {
doLog(
message: message,
osLog: osLog,
logType: .fault,
file: file,
function: function,
line: line
)
}
private static func doLog(
message: String,
osLog: OSLog,
logType: OSLogType = .default,
file: String,
function: String,
line: Int
) {
#if DEBUG
os_log(
"✌️[%@] %@ %@ L:%d %@",
log: osLog,
type: logType,
String(describing: logType),
file.split(separator: "/").last! as CVarArg,
function,
line,
message
)
#endif
}
}
これらは以下のような形で呼び出して情報を出力することができます。
Logger.info(osLog: .ui, message: "INFOボタンを押しました") // 2022-06-16 18:57:19.370911+0900 SwiftDocument[66698:1068138] [UI] ✌️[INFO] LoggerViewController.swift tappedInfoButton() L:68 INFOボタンを押しました
Logger.debug(osLog: .api, message: "DEBUGボタンを押しました") // 2022-06-16 18:57:33.986027+0900 SwiftDocument[66698:1068138] [API] ✌️[DEBUG] LoggerViewController.swift tappedDebugButton() L:72 DEBUGボタンを押しました
Logger.error(osLog: .other, message: "ERRORボタンを押しました") // 2022-06-16 18:57:53.802459+0900 SwiftDocument[66698:1068138] [OTHER] ✌️[ERROR] LoggerViewController.swift tappedErrorButton() L:76 ERRORボタンを押しました
Logger.fault(message: "FAULTボタンを押しました") // 2022-06-16 18:58:10.936951+0900 SwiftDocument[66698:1068138] ✌️[FAULT] LoggerViewController.swift tappedFaultButton() L:80 FAULTボタンを押しました
拡張することで呼び出したファイル、関数、行数なども表示できました。
Loggerでのログ出力
iOS14以降で使用できるLoggerではより直感的に柔軟な出力をすることができます。
例えば、機密情報の場合はログに出力したくない場合もあるかと思います。デフォルトでは動的な値はprivateに設定されていますが、意図的に特定の値をコンソールに公開しないためにはコードで設定をする必要があります。
以下はLoggerとos_logのそれぞれで設定した場合の違いになります。
let privateUser = "Private User"
let log = OSLog(subsystem: "com.sample", category: "Sample")
os_log("User %{private}@ logged in", log: log, type: .info, privateUser)
let logger = Logger(subsystem: "com.sample", category: "Sample")
logger.info("User \(privateUser, privacy: .private) logged in")
このようにLoggerの方が直感的に記述できることがわかるかと思います。
ログの確認方法
Xcodeのコンソールにも出力されますが、
Console.appから確認することもできます。
上記のプライベートで設定したログがどのように表示されているか確認してみましょう。
まずコンソールアプリを開きます。

使用する端末を選択し、開始ボタンを押します。

Xcodeからアプリを起動して実際にログを送ってみます。 今回は以下のログを送ります。
let logger = Logger(subsystem: "com.sample", category: "Sample")
let privateUser = "Private User"
logger.info("User \(privateUser, privacy: .private) logged in")
コンソールを確認するとログが出力されました。
ただ、Xcodeからアプリを起動している際はログの設定をプライベートにしても情報は出力されます。

では、Xcodeのアプリを終了してXcodeを経由せず、そのままアプリを起動してログを送ってみましょう。

無事にプライベートの情報を表示させないようにすることができていますね。
※ Simulatorではなく実機でないとプライベートにならないのでご注意ください。
さいごに
OSLogは今回紹介したコンソールへの情報を可視させるか以外にも様々な機能が提供されています。
まだまだ調べ切れていないところが多いですが、ログはバグを発見する手がかりになったりと開発する上で非常に重要なものでもあるので今後も引き続き理解を深めていきたいと思います。
最後まで記事を読んで頂き、ありがとうございました。
参考文献
神山義仁
iOSエンジニアです。