メインコンテンツへスキップ
見出し画像

NOT A HOTELでの楽しい滞在時間を1秒でも長く守りたい。Androidアプリのデータ収集と監視の舞台裏。

    この記事は、NOT A HOTELのソフトウェア開発連載「Inside the SOFTWARE TEAM」の第3日目です。

    はじめに


    こんにちは、NOT A HOTELでAndroidエンジニアをしています池永です。

    NOT A HOTELのアプリでは滞在中や滞在前後の体験をサポートする機能を提供しています。たとえば宿泊の予約をする、宿泊場所の鍵として使う、ホームコントローラを制御する、宿泊費の支払いをする、など多数の機能があります。

    宿泊の体験を最大限に発揮できるようにアプリの開発、運用には十分な注意を払っていますが、アプリの利用についての問い合わせや、ときには不具合についての問い合わせは完全になくすことは困難です。宿泊中のユーザーが利用するというアプリの性質上、回答や解決に即時性を求められることも多々あります。その場合にもせっかくの宿泊の体験を妨げないよう、なるべく宿泊者の負担がかからないように対応を行う必要があります。

    調査の際には、サーバー側のログにより問い合わせや不具合の解析を行うのですが、アプリとサーバー側のやり取りのログだけでは不十分なケースも起こりえます。これに備えてAndroidアプリでどのような取り組みを行なっているのかの紹介をします。

    画像
    NOT A HOTELアプリ

    操作ログの収集


    サーバー側で確認できるログ以外についても問い合わせ対応ができるよう、Androidアプリからもログを送信しています。ログの実装にはFirebase AnalyticsおよびFirebase Crashlyticsを活用しています。

    画面遷移の送信

    問い合わせされている宿泊者の状況を正しく理解するために画面遷移を記録しています。これにはFirebase Analyticsが提供するスクリーンビューを収集する機能を利用しています。

    NOT A HOTELのAndroidアプリはシングルアクティビティで構成されており、現在のバックスタックのエントリーをFirebase Analyticsのスクリーンビューとして送るだけなので数行のコードで実装できます。

    val currentBackStackEntry by navController.currentBackStackEntryAsState()
    LaunchedEffect(currentBackStackEntry) {
      val route = currentBackStackEntry?.destination?.route
      logger.logScreenView(route)
    }
    

    これにより問い合わせがあった宿泊者がどのように画面を遷移しているのかを把握することができます。以下はCrashlyticsの画像ですが、クラッシュが発生した際にもどのような画面遷移で再現したのかを知るためにも役に立っています。

    画像
    Crashlyticsでの遷移履歴の可視化例

    重要な操作の送信

    画面遷移以外にも、NOT A HOTELのサーバー側と通信していない重要な操作はログを送って解析できるようにしています。こちらはFirebase Analyticsのカスタムイベントを利用しています。

    例としてNOT A HOTELのアプリはGoogleアカウントやAppleアカウントでログインして利用するのですが、このログイン処理が該当します。ほかにもアプリの問題かどうかの切り分けのため、ブラウザに遷移したときのログなどを収集しています。

    なお、これらのログには個人を特定できる情報や宿泊の詳細、決済情報などの機微な内容は含まれていません。収集するのは問い合わせ対応や不具合解消に必要な最小限の情報に限られます。さらに、アクセス権も限られたメンバーに絞り、宿泊者の安心とプライバシー保護に配慮して運用しています。

    次の節では重要な操作の送信とその活用例としてチャット機能について紹介します。

    チャットSDKについての活用事例


    NOT A HOTELのアプリでは滞在中やその前後にコンシェルジュとチャットをする機能を備えています。チャット機能の実装にはリリース当初からサードパーティが提供するSDKを利用していました。このSDKが頻繁に初期化に失敗しており、メッセージの閲覧や送受信ができないという問題が報告されていました。

    結果的にNOT A HOTELのAndroidアプリでは今年の8月にサードパーティが提供するSDKを内製の実装に置き換えましたが、その決断に至るまでログを収集していました。サードパーティのSDKだったため、状況悪化しないかの観測と、実際の失敗率を計測して判断材料にするためです。サードパーティのSDKの不具合はNOT A HOTELのサーバー側では検知できないため、アプリからのログが必須でした。

    ログの送信

    Firebase AnalyticsのカスタムのイベントでSDKの初期化の成否を収集していました。失敗時は失敗原因も送るようにして原因の分析に努めました。

    Firebase.analytics.logEvent("chat_login") {
      param("succeeded", succeeded.toString())
      param("elapsed_time_millis", elapsedTimeMillis.toString())
      param("error_code", errorCode ?: "")
    }
    

    ログの蓄積

    BigQueryにエクスポートしたFirebase Analyticsのログは日付ごとにテーブルが分かれており、また保存期間制限があるため、別のテーブルにデータを蓄積しました。その際、日付とエラーコードごとに集約して合計数だけ蓄積するようにしました。これはデータ量が無駄に多くならないようにするのと、機密性の高いログを保存することによる情報取り扱い上のリスクを低減するためです。

    画像
    日付ごとのSDK初期化の集約結果

    ログの監視

    ログはスプレッドシートで可視化しました。開発チームだけが見られればよく、UI上でパラメータを変えたりといったニーズもないためBIツールは利用しませんでした。BigQueryからワンクリックでスプレッドシートにエクスポートできます。データの同期もスプレッドシートからUI上の操作で簡単にスケジュールできます。

    画像
    BigQueryからスプレッドシートにエクスポート

    SDKの初期化の失敗率を移動平均でグラフ化し、定期で確認することでSDKの状況の悪化に備えました。ほかにも発生するととくに復帰が難しいエラーやどのようなエラーが支配的かを可視化して監視できるようにしていました。

    画像
    SDK初期化の失敗率の可視化

    SDKの内製化というユーザーに直接価値を届けることにつながらない作業に本当に取り組むべきか、という判断はビジネス都合を考えると難しい問題です。今回のチャットのSDKについては、もちろんCSの報告内容や報告件数を第一に考慮されたと思いますが、データとして提示できたことも判断材料の1つとして貢献できたと思っています。

    宿泊者の体験を第一に


    NOT A HOTELでは宿泊者の体験を最も大切にしています。NOT A HOTELのアプリはその体験を支える一部ですが、アプリ自体を使ってもらうことを楽しんでもらうというよりは、電気のスイッチやテレビのリモコンのように使いたいときに当たり前に使える、特別に存在を意識しなくてもよい存在だと考えています。不測の事態が起きたときにも宿泊者の体験をなるべく損なうことなく対応できる状態を目指し、宿泊者が1秒でも長く宿泊を楽しんでもらえるように努めています。

    現在、NOT A HOTELのSoftwareチームでは採用強化中です。
    カジュアル面談も受け付けておりますので、お気軽にご連絡ください。

    あなたへのおすすめ