ネットワーク接続の激ムズデバッグをログ収集で解決!:生産性ガチアゲなオープンソースiOSライブラリ(4)(2/2 ページ)
iOSアプリのネットワーク状態を管理する「AFNetworking」とiOSアプリのログ出力を簡単に利用できる「CocoaLumberjack」について、概要と使い方を解説します。
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
ログレベルの設定とログ出力
次に、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標準ボタンを作成
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];
この時点で実行すると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
※ログ送信先は存在しないサンプルですので、送信時にエラーになります。
実行結果
これで完成です。実際に実行し、「Get json」ボタンを押下して少し待つと下記のようなログが出力されます。
次回は、SNS連携とBaaSの活用
以上がAFNetworkingとCocoaLumberjackの簡単な使い方でした。今回作ったサンプルもGitHubで公開しています、ぜひダウンロードしてみてください。
冒頭で説明した通り、ネットワーク接続もログ収集もアプリ開発において欠かせない要素になっていますが、実装を行う際には、ネットワーク接続もログ収集も複雑な処理を丁寧に書かなければならないため、その部分をライブラリに置き換えることができるのは品質、可読性の向上につながります。
次回はSNS連携とBaaSの活用などを紹介します。
著者プロフィール
立花 優人(たちばな ゆうと)
株式会社ソニックス Co-Founder&Architect
「TNV(作らずに、ニーズを満たし、バリューを上げる)」をモットーに各種スマートデバイスアプリケーション開発におけるシステム設計や先進技術を使用した開発に従事。「たっちー」の愛称で親しまれていると誤解している、趣味はグランドハープのミニおっさん。
平川 裕多(ひらかわ ゆうた)
株式会社ソニックス スマートデバイスソリューション事業部
板前から転身したエンジニア。iOS開発歴3年。今は自社クラウドサービス「Scirocco Cloud」の開発を日々行っています。趣味は醤油工場めぐり。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 連載「iOS SDKで始めるObjective-C入門」最新記事一覧
Windowsを使っていたけど、iOSアプリを作るためにMacを使い始めた初心者を対象に、開発ツールXcode/iOS SDKを使ってiPhone/iPadアプリを作る方法を、プログラミング言語「Objective-C」の書き方/文法を交えて解説 - Objective-C初心者のためのiOS SDKコード例一覧〜iPhone/iPadアプリ開発者が知らないと損するまとめ
iOS SDKを使った@ITのアプリ開発記事のAPIコード例へのリンク集。メソッドやクラスなどの使い方のご参考に - iPhone/iPadスマートアプリ開発レシピ
スマートフォンの「スマート」は、さまざまなセンサやハードウェアを使うところにある。本連載で、さまざまなセンサやハードウェアを使うiOS(iPhone、iPad、iPod touch)のスマートなアプリを作ってみよう - iOSでジオ(GEO)プログミラング入門
iPhone/iPad/iPod touchで動く位置情報アプリを作成するための「測位機能の取り扱い」「地図の取り扱い」「サーバとの通信」という重要なポイントを解説します - SDKで始めるiPad/iPhoneアプリ開発の勘所
初めてiPhone/iPadアプリ開発に挑戦する人が、迷わず短時間でアプリを作れるように、数多くの情報の中から要点をグっと絞った開発の勘所を紹介する入門連載です - iOSアプリ開発入門
盛り上がるiOS(iPhone・iPad・iPod touch)アプリ開発。そのハウツーや魅力に関する@IT記事一覧です