狠狠撸

狠狠撸Share a Scribd company logo
ログ管理でウキウキ 
Android Life 
2014/11/20 
Mercari Inc. 
今井智章
自己紹介 
? 株式会社メルカリ Android エンジニア(2014.3~) 
! 
! 
! 
! 
! 
! 
フリマアプリの機能開発、USアプリ開発 
? 以前はSIerでインフラ系DBエンジニア(たまにjava開発) 
2 
twitter: tomoaki_imai 
github: tomoima525 
qiita: tomoima525
Agenda 
? ウキウキするエラー系ログ管理のお話 
? ウキウキする分析系ログ管理のお話 
3
エラーログとは
ユーザーの声にならない 
叫び
ユーザーの声として上がるのはほんの一部です
エラーログ、見ましょう 
バグ、駆逐しましょう
メルカリでのエラー監視 
? Google Developer Console 
? Crashlytics 
? 自前でのリアルタイムエラーレポート 
8
Google Developer Console 
? apkをGoogle playに上げる時に時のアレ 
? アプリがクラッシュし、ユーザーがエラーレポー 
ト送付してくれた内容が見られる 
- なので大体氷山の一角 
? Crashlyticsで拾えないネイティブクラッシュが 
確認できる 
9
Crashlytics 
? 言わずと知れた有名エラーレポートサービス 
? 導入が超簡単。レポートも詳細。 
? テスト配信機能も有り 
? 最近はアカウント作成待10ちの行列ができてる
使い方 
? 一番最初に起動するActivityで呼ぶだけ 
! 
@Override 
public void onCreate(Bundle savedInstanceState) { 
com.crashlytics.android.Crashlytics.start(this); 
! 
? クラッシュ時の情報を添付することもできる 
11 
} 
com.crashlytics.android.Crashlytics.setString( 
"last_activity", this.getClass().getName());
使い方 
! 
? メルカリではdev,stg,productでパッケージ名を分け、 
それぞれでログ監視 
? テスト、QAレベルでエラーログを拾う 
12
自前エラーレポート 
? エラー用Apiでクラッシュ時に送信 
? より詳細に状況を把握し、バグ解消に活かす 
? 以下の3点が実装のポイント 
①予期せずエラーが起きてもレポートを飛ばす仕組み 
②既知のバグの発生条件を調査できる仕組み 
③レポートを貯めて送る仕組み 
13
仕組み 
①予期せずエラーが起きてもレポートを飛ばす 
仕組み 
public class ThisApplication extends Application 
implements Thread.UncaughtExceptionHandler { 
@Override 
public void uncaughtException(Thread thread, final Throwable ex) { 
new Thread() { 
public void run() { 
ByteArrayOutputStream b = new ByteArrayOutputStream(); 
ex.printStackTrace(new PrintStream(b)); 
String errMessage = b.toString(); 
gotoErrorActivityAndReport(errMessage); //エラーレポートをAPIに送る 
System.exit(1); 
}; 
}.start(); 
14 
} 
Applicationクラス内でThread.UncaughtExceptionHandlerを実装
仕組み 
②既知のバグの発生条件を調査できる仕組み 
すでにErrorが発生すると判明している部分で、try/catchし、 
catch内で調査に必要な情報を送る 
try { 
return BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options); 
} catch (OutOfMemoryError ooe) { 
postErrorReport(getCurrentActivity().getClass().getName() 
, options.inSampleSize 
, options.outWidth 
, reqWidth);     //画像処理系で画像サイズ情報を送信 
15 
}
レポートをプリファレンスに保存し、レポート送信前にクラッシュ 
したり通信できなくても、次回起動時に送付できるようにする 
public void sendErrorReportInternal(final JSONObject errReport) { 
String errMessage = JSONUtil.getString(errReport, S.message); 
if (errMessage != null) { 
Api.process(errReport, new responseListener<JSONObject>() { 
@Override 
public void onResponse(JSONObject response) {} 
@Override 
public void onErrorResponse(JSONObject response) { 
ErrorStore.addErrReport(errReport); //プリファレンスに保存 } 
//以下略 
仕組み 
③レポートを貯めて送る仕組み 
public void onResume() { 
sendOldErrorReports(); //以前のレポートがあった場合は送信 
} 
16
まとめ 
? Crashlyticsで届かないかゆいところに自前エ 
ラーレポートを組み合わせるとバグ駆逐が捗る 
Google 
Analytics Crashlytics 自前 
17 
ログのわかりや 
すさ△ ? ◎ 
カスタマイズ性? △ ◎ 
導入容易性default ? △
ウキウキしましたか?
続いて、分析ログの话
What is 分析ログ? 
? インストール率, DAU, 売上, A/B testing etc. 
を分析するためのログ 
? 用途によって様々なサービスがある 
20
分析ログ(サービス)の問題点 
? それぞれの分析サービスのApiに標準性がない 
- 似たようなトラッキングコードをひたすら書かされる 
- その割にApiごとに癖があって実装に困る 
- 新しいライブラリを追加する度に導入の調査が必要になる 
21
そうだ、Segment 
使おう
Segment 
? 複数の分析サービスを統合できる 
? シンプルなAPIで導入が簡単 
? けどかなり詳細に分析データを送信できる! 
23
Segment 
? SegmentのApiで多くの分析サービスをカバー 
? ユーザーはコンソールから分析サービスを選ぶ 
だけ 
24
実装例 
? 事前準備 
- アカウントの用意 
- https://segment.com/ 
- プロジェクトの作成 
- 組織単位でproject作成が可能 
- API keyを確認 
25 
こちらにまとめました↓ 
http://qiita.com/tomoima525/items/bab086d341b686b9f8a1
実装例 
? gradleのdependencies追加(Android Studio) 
dependencies { 
compile('com.segment.analytics.android:core:+@aar') { 
transitive = true 
} 
//必要なライブラリのみ追加 
compile 'com.google.android.gms:play-services:+' 
compile ‘com.mixpanel.android:mixpanel-android:+@aar' 
} 
! 
! 
! 
Eclipse向けにjarファイルもある(ただしバージョンは古い) 
! 
? AndroidManifest.xmlへの設定 
<uses-permission android:name=“android.permission.INTERNET”/>   //必須 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 
<uses-permission android:name="android.permission.READ_LOGS"/> 
<uses-permission android:name="android.permission.GET_TASKS"/> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 
26
実装例 
? res/values/analytics.xmlにAPI keyを設定 
<resources> 
<string name="analytics_write_key">YOUR_WRITE_KEY</string> 
<string name="analytics_logging">true</string> 
<integer name="analytics_queue_size">20</integer> 
</resources> 
analytics_write_key: 
   コンソールで確認したApi key 
analytics_logging: 
   logに送信データが出力 
   うまく確認できなかった。iOSでは見られる? 
analytics_queue_size: 
   一度のキューで送信するイベントの数 
   キューがたまらなくても一定時間で送信されている様子 
27
代表的なトラッキングメソッド 
? identify 
アプリユーザーのIDを設定する 
Analytics.with(context).identify(user_id); 
複数のTraits(特徴)を設定することも可能 
Analytics.with(context).identify(new Traits().putName(“Moge Hoge")); 
Analytics.with(context).identify( 
new Traits().putEmail(moge@hoge.com")); 
Traitsはage, gender等多数あり、分析サービスに応じて設定可能 
https://segment.com/docs/api/tracking/identify/#special-traits
代表的なトラッキングメソッド 
? Alias 
会員登録前後のIDを紐つけ、会員登録前のイベントを関連付けする 
Mixpanel、Flurryといった分析サービスで利用 
Analytics.with(context).alias(uuid, new_id); 
//会員登録前のIDがない場合はSegment内のanonymousIDが紐付けられる 
※Segmentのエンジニア曰く統合がまだ十分でないらしく、 
今後も変わる可能性あり
代表的なトラッキングメソッド 
? Track 
あらゆるイベントにプロパティ、トラック名をつけてトラックする 
Properties properties = new Properties() 
.putValue("price", price) 
.putValue("category", CategoryId); //オブジェクト型を設定できる 
Analytics.with(context).track(trackName, properties); 
プロパティは任意のキーを設定できる
デバッガー 
? コンソールデバッガーで値を確認できる 
{ 
"messageId": "09361829-c11c-451d-83d0-d1e2e9fc9063", 
"type": "track", 
"anonymousId": "d6c327e4-76c3-418c-907e-4b0eba89ec40", 
// 中略 
"timestamp": "2014-11-19T11:34:54.000Z", 
"event": "Eat Curry", 
"properties": { 
"price": 1200, 
"category": "Indian", 
"condition": "good", 
}, 
} 
値はjsonでも取得可能
分析 
? コンソールから分析サービスを選ぶ 
それぞれの分析サービスに必要な滨顿や办别测を设定するだけ
分析ツールの追加があっても 
ライブラリ、ソースコードの 
追加は(ほとんど)不要
スッキリ
ちょっと注意 
? 成長中のサービスなので、開発がさかん 
? Documentの記述が食い違っている所もある 
? ソースコードが食い違っている所がある(!) 
? オープンソースなのでおかしかったら迷わずPR 
35
まとめ 
? エラーログ管理はカスタマイズするとバグ駆逐 
が捗ってウキウキ 
? 分析ログはSegment使うと楽ちん、スッキリで 
ウキウキ 
36
メルカリでは础苍诲谤辞颈诲/颈翱厂エンジニア募集中!

More Related Content

ログ管理でウキウキAndroid Life (Log Management in Android)