Firebase Analyticsを入れたはずなのに、コンソールにデータが来ない。そういう状態で何ヶ月も運用していたことに気づいた。
DebugViewで確認してみた
いくつかのアプリでAnalytics Dashboardが0のまま動いていなかった。原因を調べるためにXcodeの起動引数に -FIRAnalyticsDebugEnabled を追加して実機で動かしてみた。
コンソールを見ると、こう出ていた。
[FirebaseCrashlytics] Firebase Analytics SDK not detected.
Crash-free statistics and breadcrumbs will not be reported
これはCrashlyticsが出したメッセージだ。Crashlytics自体は import FirebaseCrashlytics があったので正常に動いていた。ただAnalyticsが見当たらないから、クラッシュレポートにスクリーンビューのブレッドクラムが付かない・クラッシュフリー統計がAnalyticsと連携できない、という状態を教えてくれた形だ。
原因はふたつの欠け
調べてみるとふたつのことが重なっていた。
ひとつは import FirebaseAnalytics が書かれていないこと。Swiftのリンカーは参照されていないコードをデッドコードとして除去する。FirebaseApp.configure() を呼んでいても、AnalyticsモジュールをSwiftから参照していなければ、ビルド時に丸ごと取り除かれてしまう。
// これだけでは足りない
import FirebaseCore
FirebaseApp.configure()
// こうする
import FirebaseCore
import FirebaseAnalytics // これが必要
FirebaseApp.configure()
もうひとつは -ObjC リンカーフラグがないこと。Firebase AnalyticsはObjective-Cの +load メソッドを使って自分自身を初期化の仕組みに登録する。このフラグがないとObjective-Cのランタイムフックが正しく読み込まれず、Analyticsが起動しない。
SPMで追加していても同じで、Firebase AnalyticsはSPM経由でも静的バイナリ(static XCFramework)として配布されている。静的リンクの場合、参照されていないコードはリンカーが除去するため、-ObjC で明示的に「Obj-Cのクラスは全部含めろ」と伝える必要がある。
Xcode → Target → Build Settings → Other Linker Flags に -ObjC を追加する。
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
);
どちらか片方でも欠けていると動かない。FirebaseCoreやCrashlyticsは普通に動くのにAnalyticsだけ無効、という状態になる。
import Firebase でまとめて書いている場合は?
import Firebase という書き方をしているアプリは今回の影響を受けにくい。Firebase傘モジュールをインポートすることでAnalyticsへの参照がリンカーに伝わり、除去されずに済む。
ただし -ObjC フラグについては傘インポートの有無に関わらず必要になるケースがある。安全のために追加しておく方がいい。
DebugViewを使うとイベントが見える
-FIRAnalyticsDebugEnabled を起動引数に追加した状態で動かすと、DebugViewにリアルタイムでイベントが流れてくる。screen_view や ad_impression など、実装していなくても自動で収集されるイベントが確認できる。
修正後にコンソールに出てきたログはこんな感じだ。
[FirebaseAnalytics] Analytics v.12.0.0 started
[FirebaseAnalytics] Debug mode is on
[FirebaseAnalytics] Analytics is ready to receive events
[FirebaseAnalytics] Analytics collection enabled
これが出れば正常。
気づきにくいのが厄介
アプリ自体は普通に動く。クラッシュも起きない。ただ静かにデータが来ないだけ。半年以上そのままだったアプリもあった。
入れたつもりが動いていない、というのはどこでも起きる話だと思うが、Analyticsは症状が地味なので特に気づきにくい。実装したらDebugViewで確認する、というのを手順に入れておくと発見が早い。