Upgrade to Pro — share decks privately, control downloads, hide ads and more …

STORES 決済で使っているLoggerの実装を刷新した話

k-kohey
October 20, 2022
170

STORES 決済で使っているLoggerの実装を刷新した話

k-kohey

October 20, 2022
Tweet

Transcript

  1. 2022/10/20 【Da Vinci Studio/ロコガイド/Chatwork/STORES】iOS Meetup
    STORES 決済で使っているLoggerの実装を刷新した話
    k-kohey
    (@k_koheyi)

    View Slide

  2. 概要
    - STORES 決済(iOS)で利用しているロガー実装を刷新した
    - ユーザ行動やシステムの不具合などのログを収集する実装を
    ロガー実装とする
    - どのような背景で既存の実装に問題があったか
    およびそれをどう対応したかについて発表します🙌
    2

    View Slide

  3. 背景 | STORES 決済が提供するサービス
    3
    - STORES 決済では決済に関するサービスを
    下記の2つの形で提供している
    - STORES 決済を介して
    クレジットカードや電子マネー決済ができる
    - 決済アプリ(以降、アプリと呼ぶ)
    - App Storeにて
    公開しているアプリ
    - 決済SDK(以降、SDKと呼ぶ)
    - 決済機能を自社アプリに組み込みたい
    企業向けに公開しているSDK

    View Slide

  4. 背景 | ログの活用
    アプリではサービス改善に役立てるため
    ユーザ行動やシステムの不具合をログとしてバックエンドに送信している
    4
    バックエン
    ドA
    バックエン
    ドB
    バックエン
    ドC
    ユーザ行動や不具合を蓄積するバックエンド
    決済が
    失敗しました
    決済が
    失敗しました
    開発者

    View Slide

  5. 背景 | ログの活用
    バックエンドに送信されたログから下記のような事がわかる
    - システムに不具合が生じていること
    - および不具合が発生している箇所
    - ユーザがアプリに対してどのような操作を行なっているか
    これらの情報は下記のような改善に役立ちます
    - システムに問題が発生した際に早期に発見し修正すること
    - ユーザの操作からボトルネックを発見し使いやすいアプリにすること
    5
    ログは継続的なサービス開発において重要

    View Slide

  6. 背景 | SDKにおけるロギングの問題
    一方でSDKは後述する理由からログを送信できておらず(※)
    ログの恩恵を十分に得られていない状態だった
    6
    バックエンド
    A
    バックエンド
    B
    バックエンド
    C
    ユーザ行動や不具合を蓄積するバックエンド
    アプリが起動
    されたわよ
    (※)クライアントのログ情報に限った話です。バックエンドでは収集できています。

    View Slide

  7. 背景 | SDKにおけるロギングの問題
    - アプリとSDKでは次のような外部のライブラリの利用に対して
    異なる考え方で開発を進めている
    - SDKは外部のライブラリを利用しない方針で開発している
    - SDKは外部(SDKクライアント)から利用されることを前提にしている
    - SDKクライアントとSDKが同じライブラリを利用する場合に、
    そのライブラリのバージョンを解決できない可能性がある
    - アプリは外部のライブラリを利用している
    - アプリにはクライアントが存在せず、SDKと同じ考えは必要ないため
    - アプリはFirebaseやMixpanel等の一般公開されている
    ライブラリを利用してログを収集している
    7
    SDKはアプリと同様の方法でロギングできない

    View Slide

  8. 背景 | SDKにおけるロギングの問題
    - アプリとSDKでは次のような外部依存に対して異なる考え方で
    開発を進めている
    - SDKは外部のライブラリを利用しない方針で開発している
    - SDKは外部(SDKクライアント)から利用されることを前提にしている
    - SDKクライアントとSDKが同じライブラリを利用する場合に、
    そのライブラリのバージョンを解決できない可能性があるため
    - アプリは外部のライブラリを利用している
    - アプリにはクライアントが存在せず、SDKと同じ考えは必要ないため
    - アプリはFirebaseやMixpanel等の一般公開されている
    ライブラリを利用してログを収集している
    8
    SDKはアプリと同様の方法でロギングできない
    SDKでもロギングできるように
    ロガーの実装を刷新することに

    View Slide

  9. 実装 | 方針
    SDKがロギングできるようになるだけではなく、アプリとロギングの処理を共通化
    する上で次の事を実現したいと考えた
    - アプリとSDKで同じインタフェースを介してロギングするが
    どういう実装でバックエンドとコミュニケーションするかは
    アプリとSDKで柔軟に切り替えられるようにしたい
    - アプリでは外部のライブラリを用いたい。SDKでは用いない。
    - アプリとSDKでログのパラメータを変更したい
    - 例えばアプリではアプリのバージョン、SDKではSDKのバージョンを付与する
    9

    View Slide

  10. 実装 | 方針
    10
    ロガーの実装をする上で次の事は気をつけたいと考えた
    - ログの欠損を防ぐため、送信に失敗したログは端末に保存したい
    - 簡単に新しいイベントログを追加したい

    View Slide

  11. 実装 | ロガー実装の共通化
    11
    ログ収集SDK
    Firebaseや
    MixPanel(※)等の
    SDK
    ログ収集SDK
    Firebaseや
    MixPanel(※)の
    SDK
    ロガー実装
    アプリから
    DIして参照
    MixPanelの
    HTTPクライアント
    必要に応じてSDKから
    DIして参照
    SDKを介して参照
    追加
    追加
    (※)弊社にて使っている分析ツール

    View Slide

  12. 実装 | ロガー実装の共通化
    12
    ロガー実装
    MixPanelの
    HTTPクライアント
    SDKから
    DIして参照
    他社
    アプリ
    (SDKクライアント)
    アプリからFirebaseや
    Mixpanl等のSDKの実装
    をDIされない場合でも
    SDKのロガー実装から
    ログが可能
    ログ収集SDK
    Firebaseや
    MixPanel等の
    SDK
    ロガー実装
    アプリから
    DIして参照
    SDKを介して参照
    SDKからアプリの
    ロガー実装を参照
    し利用できる
    💡アプリとSDKのどちらの利用においても
    同じインタフェース(ロガー実装)で
    バックエンドを意識せずログが可能に

    View Slide

  13. 実装 | ロガー実装の共通化
    13
    左のようなインタフェースで次の
    ように条件に応じてロガーの実装
    を切り替えられるようにした
    - アプリからの利用時は
    backendBLogger
    - それ以外の時は
    backendALogger
    注) 決済アプリは外部に公開している決済SDKとほぼ同等の機能を持つ異なるSDKを利用し
    ています。そのためloggerインスタンスは外部に公開されません

    View Slide

  14. 実装 | ログのMutation
    14
    {
    "eventName": "signin",
    "parameters": {}
    }
    {
    "eventName": "signin",
    "parameters": {
    "sdk_version":
    "1.0.0"
    }
    }
    {
    "eventName": "signin",
    "parameters": {
    "app_version":
    "5.5.2"
    }
    }
    - SDKとアプリでログのパラメータ
    を柔軟に変更したい
    - 例
    - SDKの場合は全てのログ
    のパラメータにsdk_versionを
    付与
    - アプリの場合は全てのログ
    のパラメータにapp_versionを
    付与
    - ただしSDKとアプリでログ定義は
    同じものを使い回したい
    - 同じログを2重管理はしたくない
    ログを変換する層が必要

    View Slide

  15. 実装 | ログのMutation
    15
    {
    "eventName": "signin",
    "parameters": {}
    }
    {
    "eventName": "signin",
    "parameters": {
    "sdk_version": "1.0.0"
    }
    }
    {
    "eventName": "signin",
    "parameters": {
    "app_version": "5.5.2"
    }
    }
    Mutation
    - ログを変化する層 Mutation を用意
    - ログは必ずMutationを介して任意の形に変形されて送信される

    View Slide

  16. 実装 | ログのMutation
    16
    {
    "eventName": "signin",
    "parameters": {}
    }
    {
    "eventName": "signin",
    "parameters": {
    "os": "16.0"
    }
    }
    他にも全てのログのパラメータに入るような汎用的な情報の挿入や
    パラメータの変換に使えます💡
    {
    "eventName": "signin",
    "parameters": {}
    }
    {
    "eventName": "signin",
    "parameters": {
    "network": "wifi"
    }
    }
    {
    "eventName": "failed",
    "parameters": {
    "error": MyError.invalidSyntax
    }
    }
    {
    "eventName": "signin",
    "parameters": {
    "error description": "invalid
    syntax"
    }
    }

    View Slide

  17. 実装 | ログの定義を容易にする工夫
    - 従来は左図のようにenumを使って
    ログ定義を管理しており
    新規にイベントを追加する際は
    caseを追加して対応していた
    - ログを増やすとコンパイルエラーが
    発生しenumのプロパティに対して修正が
    必要だった
    17
    enumのパターンマッチングが安全装置
    として働いている一方で
    拡張に対して開いていないと感じる

    View Slide

  18. 実装 | ログの定義を容易にする工夫
    - ログ定義はenumではなく
    structを採用
    - ログのカテゴリーごとにstructを作り
    そのstaticなプロパティやメソッドにて
    各ログを定義
    - structの場合は単に定義を
    増やしていくだけで
    ログを追加していくことが可能
    18

    View Slide

  19. 実装 | ログの欠損を防ぐ工夫
    ログを送信するコードを記述しても
    ネットワークが不安定なときなどにログの送信が失敗する懸念がある
    19
    失敗時はログをBufferに貯めてリトライする
    Bufferの実装がDatabaseやファイルシステムに依存していると
    複数のスレッドからBufferに書き込みを行うとクラッシュする恐れがある
    Swift ConcurrencyのActorを利用

    View Slide

  20. 結果
    - 以上までの事を組み合わせた実装を行い下記のようなインタフェースで
    アプリとSDK両方からログを送信できるようになった
    20
    - ほぼ同等の実装をGitHubに公開中(SPMで導入可)
    - https://github.com/k-kohey/Parchment-swift

    View Slide

  21. おわりに
    ● SDKとアプリと共有して使うロガーの実装をした
    ● 具体的なログの実装はアプリからDIすることによって
    SDKが直接依存を持たないFirebaseやMixpanel
    にロギングを命令できるようにした
    ● Mutationと呼ばれる仕組みを導入しパラメータの変更も容易にした
    ● 実装はGitHubにOSSとして公開している
    ○ Starください
    21
    k-kohey
    STORES 決済で使っているLoggerの実装を刷新した話

    View Slide