連載
» 2013年11月07日 18時00分 公開

ネットワーク接続の激ムズデバッグをログ収集で解決!生産性ガチアゲなオープンソースiOSライブラリ(4)(2/2 ページ)

[立花優人, 平川裕多,ソニックス]
前のページへ 1|2       

iOSアプリのログ出力を簡単に利用できる「CocoaLumberjack」

 CocoaLumberjackは、ログ出力を簡単に利用できるようにしたライブラリです。下記のログを出力できます。これは1つだけ行うようにすることも、全て行うことも可能です。

  • DDTTYLogger:Xcodeのコンソールに出力
  • DDASLLogger:Appleのシステムロガーに出力
  • DDFileLogger:ファイルに出力

 ここではCocoaLumberjackでログをファイルに保存し、一定間隔でAFNetworkingを使いログを送信します。せっかくなので、AFNetwokingのサンプルコードに追記していく形で紹介します。

CocoaLumberjackを使うための準備

 まず、CocoaLumberjackは下記URLからダウンロードします。

 その中にある「Lumberjack」ディレクトリをAFNetwokingのプロジェクトに追加します。

 次に、「CustomLogFileManager」(後述)を作成するので、AFNetwokingSampleの部分でメニューを出し、[New File ...]を選択します。その後、以下のように[Objective-C class]を選択して、[Next]を選択します。

 次に以下のように指定して[Next]を選択し、次に出てきたダイアログでは[Create]をそのまま選択します。

 ファイルを追加する作業は以上です。現段階でのプロジェクトの状態は以下の通りです。

CocoaLumberjackを使うためのpchファイルの変更

 それではコードをいじっていきましょう。まずCocoaLumberjackを全てのクラスで扱えるように、AFNetworkingSample-Prefix.pchを変更します。

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import <SystemConfiguration/SystemConfiguration.h>
    #import <MobileCoreServices/MobileCoreServices.h> // 追加
    #import "DDLog.h"
#endif
// 追加 ビルドがデバッグの時はVERBOSEレベルのログまで
// リリースの時はERRORだけを出力する
#ifdef DEBUG
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#else
static const int ddLogLevel = LOG_LEVEL_ERROR;
#endif
AFNetworkingSample-Prefix.pch

ログレベルの設定とログ出力

 次に、AppDelegateにCocoaLumberjackの中にはDDLogというクラスがあり基本的にこれを利用して、設定とログ出力を記述します、DDLogでは下記のログ出力メソッドがあります、ログレベルに応じて使い分けましょう。

  • DDLogError
  • DDLogWarn
  • DDLogInfo
  • DDLogVerbose
#import "AppDelegate.h"
#import "AFNetworking.h"
#import "DDTTYLogger.h"
#import "CustomLogFileManager.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // DDLog初期設定
    CustomLogFileManager *logFileManager = [[CustomLogFileManager alloc] init];
    // ファイルにログを出力
    DDFileLogger *fileLogger = [[DDFileLogger alloc] initWithLogFileManager:logFileManager];
    // 1日に1回ログファイルを更新
    // fileLogger.rollingFrequency =   60 * 60 * 24;
    // 10秒に1回ログファイルを更新
    fileLogger.rollingFrequency =   10;
    // ログファイルを残す数
    fileLogger.logFileManager.maximumNumberOfLogFiles = 7;
    // Xcodeのコンソールにログを出力
    [DDLog addLogger:[DDTTYLogger sharedInstance]];
    [DDLog addLogger:fileLogger];
    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    // ios標準ボタンを作成
AppDelegate.m

API接続の結果をログ出力

 続いて、API接続の結果をログ出力します。

[AFJSONRequestOperation JSONRequestOperationWithRequest:request
                                                    success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json) {
                                                        // 成功した場合
                                                        // UILabelに表示 AFNetworkingはjsonを使いやすい形に渡してくれる
                                                        [self.label setText:
                                                         [NSString stringWithFormat:
                                                          @"TotalResult : %@", [json valueForKeyPath:@"TotalResult"]
                                                         ]
                                                        ];
                                                        DDLogInfo(@"TotalResult : %@", [json valueForKeyPath:@"TotalResult"]);
                                                    } failure:^(NSURLRequest *req, NSHTTPURLResponse *res, NSError *e, id json) {
                                                        // 失敗した場合、この時点でネットワークにつながっていない、タイムアウト、urlが間違っているなどで、ここに来る
                                                        // NSLog(@"%@", e.localizedDescription);
                                                        DDLogError(@"%@", e.localizedDescription);
                                                    }];
    [operation start];
AppDelegate.m

 この時点で実行するとXcodeにログが出力され、ログファイルは確認できませんが、保存はされていきます。

ログ内容が記述されたJSONファイルを送信

 このままでは、ただログを出力しただけなので、ファイルを送信する処理を記述します。先ほど作ったCustomLogFileManagerは、ここで利用します。

 CustomLogFileManagerで継承したLogFileManagerDefaultはメソッド「didRollAndArchiveLogFile」を持っていて、これを記述するとログファイルが更新されるタイミングで呼ばれるようになります、それを利用して、ログ内容を送信します。

#import "CustomLogFileManager.h"
#import "AFNetworking.h"
@implementation CustomLogFileManager
// ログファイルが更新される際に呼ばれる
-(void)didRollAndArchiveLogFile:(NSString *)logFilePath
{
    // ログファイルのパスからログ内容を取得
    DDLogFileInfo *info = [DDLogFileInfo logFileWithPath:logFilePath];
    NSString* content = [NSString stringWithContentsOfFile:info.filePath
                                                  encoding:NSUTF8StringEncoding
                                                     error:NULL];
    // ログを送信
    [self postLogData:content];
}
-(void)postLogData:(NSString *) data
{
    // ログデータを表示するのでここはNSLogを使用する
    NSLog(@"post data : %@", data);
    // ※https://sample.urlは存在しないURLですので、失敗になりますが
    // このようにエラーログなどをサーバに送ることでログ収集が可能です
    NSURL *url = [NSURL URLWithString:@"https://sample.url"];
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
    NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
                            data, @"log",
                            nil];
    [httpClient postPath:@"/log/save" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
        // 成功時
        NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
        DDLogVerbose(@"Request Successful, response '%@'", responseStr);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        // 失敗時
        DDLogError(@"[HTTPClient Error]: %@", error.localizedDescription);
    }];
}
@end
CustomLogfileManager.m

※ログ送信先は存在しないサンプルですので、送信時にエラーになります。

実行結果

 これで完成です。実際に実行し、「Get json」ボタンを押下して少し待つと下記のようなログが出力されます。

次回は、SNS連携とBaaSの活用

 以上がAFNetworkingとCocoaLumberjackの簡単な使い方でした。今回作ったサンプルもGitHubで公開しています、ぜひダウンロードしてみてください。

 

 冒頭で説明した通り、ネットワーク接続もログ収集もアプリ開発において欠かせない要素になっていますが、実装を行う際には、ネットワーク接続もログ収集も複雑な処理を丁寧に書かなければならないため、その部分をライブラリに置き換えることができるのは品質、可読性の向上につながります。

 次回はSNS連携とBaaSの活用などを紹介します。

著者プロフィール


立花 優人(たちばな ゆうと)


株式会社ソニックス Co-Founder&Architect

「TNV(作らずに、ニーズを満たし、バリューを上げる)」をモットーに各種スマートデバイスアプリケーション開発におけるシステム設計や先進技術を使用した開発に従事。「たっちー」の愛称で親しまれていると誤解している、趣味はグランドハープのミニおっさん。


平川 裕多(ひらかわ ゆうた)


株式会社ソニックス スマートデバイスソリューション事業部

板前から転身したエンジニア。iOS開発歴3年。今は自社クラウドサービス「Scirocco Cloud」の開発を日々行っています。趣味は醤油工場めぐり。


前のページへ 1|2       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。