iOSアプリのリモートログビュアー（NSLogger）

## iOSアプリのリモートログ取得について
iOS10からOSのログが大量に出るようになり、またコンソールログで日本語が文字化けすることもあり、アプリログを個別でリモート監視したいと考えていました。

そこで[NSLogger](https://github.com/fpillet/NSLogger)（https://github.com/fpillet/NSLogger) というリモートログアプリを利用してみました。
このNSLoggerはリモートログの送信クライアントライブラリと受信ビュアーアプリで構成されていますが、使いやすくまたメンテナンスも継続されているところが良いです。

このアプリは、ビュアーとクライアントライブラリで構成されており、ビュアーは公開されているソースコードからビルド（要Mac開発者ライセンス）またはバイナリで提供されています。

## iOSアプリへの組み込み

### アプリへの組み込み方
githubサイトに書いてある通り、

1. cocoapodsまたはcarthageでフレームワークをプロジェクトファイルに組み込む
2. ログ出力用のクラスを作成してアプリで利用する

になります。
アプリ側でのログ出力用クラスのサンプルを下記に記載します。
LOGFILEは、オフライン時のログバッファ用ファイル名。iOS端末のテンポラリディレクトリに記録されます。
SERVICE_NAMEはBonjourのService Nameです。NSLoggerのPreferences->Networkの設定で設定する値と合わせます。

```LogManager.swift
import NSLogger

class LogManager {
    
    static let LOGFILE_NAME = "logging_data"
    static let SERVICE_NAME = "test"
    static let DEBUG_LEVEL  = 0

    // 初期化
    static func start() {
        
        // インスタンス生成
        let logger = LoggerGetDefaultLogger()
        
        // オフラインロギングファイル設定、Bonjour設定
        let paths = NSTemporaryDirectory()
        let file = "\(paths)/\(LOGFILE_NAME)"
        LoggerSetBufferFile(logger, file as CFString!)
        LoggerSetOptions(logger, UInt32(
                                 kLoggerOption_BufferLogsUntilConnection |
                                 kLoggerOption_BrowseBonjour |
                                 kLoggerOption_BrowseOnlyLocalDomain))
        LoggerSetupBonjour(logger, nil, SERVICE_NAME as CFString!)
        
        // ロギングスタート
        LoggerStart(logger)
    }
    
    // ログ出力
    static func print(format: String!, args: CVarArg...) {
        let appID = Bundle.main.bundleIdentifier
        LogMessage_va(appID, Int32(DEBUG_LEVEL), format, getVaList(args))
    }
}
```

呼び出し方法
最初にLogManager.start()で初期化
以降は下記例のようにprintメソッドでログ出力  

- LogManager.print(format:"日本語")
- LogManager.print(format:"%@:%@", args:#function,"テスト")

Objective-Cのサンプルも挙げておきます。

```LogManager.h
@interface LogManager : NSObject
+(void)start;
+(void)print:(NSString*)format, ...;
@end
```

```LogManager.m
#import "LogManager.h"
#import <NSLogger/NSLogger.h>

@implementation LogManager

#define LOGFILE_NAME @"logging_data"
#define SERVICE_NAME @"test"
#define DEBUG_LEVEL 0

// 初期化
+(void)start
{
    // インスタンス作成
    Logger *logger = LoggerGetDefaultLogger();
    
    // オフラインロギングファイル設定、Bonjour設定
    NSString *tmpDirPath = NSTemporaryDirectory();
    NSString *file = [NSString stringWithFormat:@"%@/%@",tmpDirPath,LOGFILE_NAME];
    LoggerSetBufferFile(logger,(__bridge CFStringRef)file);
    LoggerSetOptions(logger,kLoggerOption_BufferLogsUntilConnection |
                            kLoggerOption_BrowseBonjour |
                            kLoggerOption_BrowseOnlyLocalDomain);
    LoggerSetupBonjour(logger, nil, (__bridge CFStringRef)SERVICE_NAME);
    
    // ロギングスタート
    LoggerStart(logger);
}

// ログ出力
+(void)print:(NSString*)format,...
{
    NSString *appID = [[NSBundle mainBundle] bundleIdentifier];
    va_list args;
    va_start(args, format);
    NSString *message = [[NSString alloc]initWithFormat:format arguments:args];
    va_end(args);
    LogMessage_va(appID, DEBUG_LEVEL, message, nil);
}
@end
```

呼び出し方法
最初に[LogManager start]で初期化
以降は下記例のようにprintメソッドでログ出力

- [LogManager print:@"日本語"];
- [LogManager print:@"%s:%@",\_\_FUNCTION\_\_,@"テスト"];

## ビュアー用意

サイトにmacOS用のビュアーとiPad用のビュアーのソースコードがあります。macOS用のビュアーはバイナリもあります。
ダウンロードして起動したら上記にある通り、PreferencesのBonjour Service Nameを設定します。
ログを送信するiOS端末とビュアーを動かしているMacが同じWiFiにいれば、Bonjourによりログがビュアーに送信されます。

<img width="969" alt="nslogger_sc.png" src="https://qiita-image-store.s3.amazonaws.com/0/84490/8c940970-18e8-32b8-7db2-f325b96f7eee.png">

### 最後に

まだ少ししか使っていないのですが、使いやすいツールかなと思います。
ログについては文字だけでなく、バイナリデータや画像も送れるとのことです。
各画面のスクリーンショットをログとして送るのにも使えそうですね。