SwiftyBeaver
SwiftyBeaver というログ集計プラットフォームがあり、これを利用するとアプリケーションのログをクラウドに保存することができます。
それ以外にも普通にコンソールにログを吐いたりローカルのファイルに保存してくれる機能があります。
ログをメールで送れる
今回はローカルにログを保存する機能を使って、そのログファイルをメールで送信できるようにします。
テスターさんが「アプリクラッシュしたんだが」と言ってきた場合に、メールでアプリケーションログを送信できるようにすれば手順やデータなどが再現できるようになりますね。
ログを送信できるようにする手順
Getting Started - SwiftyBeaver Docs
途中までここに載っている内容です。
まずログを出力する
Install SwiftyBeaver
Carthage や Cocoapods などで SwiftyBeaver を install します。
github "SwiftyBeaver/SwiftyBeaver"
or pod 'SwiftyBeaver'
などですね。
AppDelegate で import
AppDelegate のトップレベルで log の設定を書きます。
Release では利用しない前提なので、私は以下のように書いています。
import SwiftyBeaver
let log: SwiftyBeaver.Type? = {
#if DEBUG
let logger = SwiftyBeaver.self
let console = ConsoleDestination()
console.asynchronously = false
let file = FileDestination()
logger.addDestination(console) // コンソールにログを出力する
logger.addDestination(file) // ファイルにログを出力する
return logger
#else
return nil
#endif
}()
コンソールログを確認する
log?.debug("\(a), \(b)")
と書きました。ちゃんとログが出ていますね。

ログファイルの取得
SwiftyBeaver では Library/Cache ディレクトリにログが吐き出されます。
Cache は OS 側が容量などに合わせて自動で削除するものなので、ログが肥大化しても OS 側がよしなにやってくれそうですね。
以下のコードでログファイルにアクセスし、ファイルのデータを取得できます。
let path: String = NSHomeDirectory() + "/Library/Caches/swiftybeaver.log"
if FileManager().fileExists(atPath: path) {
let url = URL(fileURLWithPath: path)
let data = try? Data(contentsOf: url)
}
MessageUI.framework の import
今回はログファイルをメールで送信したいので、 MessageUI.framwork を利用します。
【Swift】アプリからメーラーを起動する方法 - Qiita にわかりやすい導入方法が書いてあります。
ログファイルをメールで送る
以下のようなコードでメールを送るようにしました。
sendMail()
を実行するボタンは #if DEBUG
の時だけ表示するようにしています。
import MessageUI
extension HogeViewController {
fileprivate func sendMail() {
let path: String = NSHomeDirectory() + "/Library/Caches/swiftybeaver.log"
if FileManager().fileExists(atPath: path) {
if MFMailComposeViewController.canSendMail() {
let url = URL(fileURLWithPath: path)
let data = try? Data(contentsOf: url)
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(["送信先メールアドレス"])
mail.setSubject("アプリログ")
mail.setMessageBody("問題の事象などを書いてください", isHTML: false)
mail.addAttachmentData(data!, mimeType: "text/plain", fileName: "log.txt")
present(mail, animated: true, completion: nil)
} else {
log?.warning("メールが利用できない設定になっています。")
}
} else {
log?.warning("ログファイルが見つかりませんでした。")
}
}
}
extension SettingViewController: MFMailComposeViewControllerDelegate {
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
log?.info(result.rawValue)
dismiss(animated: true, completion: { [weak self] _ in
switch result {
case .sent:
log?.info("送信成功")
case .failed:
log?.error("失敗")
default:
break
}
})
}
}
メール送信画面
こんな感じで表示されます。

受信したメール
このようにメールが受信できました。
添付ファイルを開くと、アプリケーションのログを見ることができます。

おわり
アプリの内部だけでログを集計し、それを外部に送れる仕組みを作りました。
手順や状況などが把握しやすいため、デバッグに非常に役立つと思います。
ただし、これは綺麗にログを吐いていないと意味がないため、ログレベルや何をログとして送信するかなどをちゃんと考えないといけませんね
SwiftyBeaver のクラウドログ機能もめちゃくちゃ便利そうなので、クラウド版の導入も考えていきたいです
2017/03/23 23:39 追記
ログのサイズがメール送信可能ファイルサイズを超える気がしてきたのでその事象に当たったらまた更新します。