LoginSignup
27
17

More than 5 years have passed since last update.

SwiftyBeaver でアプリケーションログをメール送信しデバッグしやすい環境を作る

Last updated at Posted at 2017-03-23

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)") と書きました。ちゃんとログが出ていますね。

スクリーンショット 2017-03-23 20.19.43.png

ログファイルの取得

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
            }
        })
    }
}

メール送信画面

こんな感じで表示されます。

2017-03-23 20.45.25.png

受信したメール

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

スクリーンショット 2017-03-23 20.47.20.png

おわり

アプリの内部だけでログを集計し、それを外部に送れる仕組みを作りました。
手順や状況などが把握しやすいため、デバッグに非常に役立つと思います。

ただし、これは綺麗にログを吐いていないと意味がないため、ログレベルや何をログとして送信するかなどをちゃんと考えないといけませんね :relaxed:

SwiftyBeaver のクラウドログ機能もめちゃくちゃ便利そうなので、クラウド版の導入も考えていきたいです :moneybag:

2017/03/23 23:39 追記

ログのサイズがメール送信可能ファイルサイズを超える気がしてきたのでその事象に当たったらまた更新します。

27
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
17