この記事は NewsPicks Advent Calendar 2025 の23日目の記事です。
こんにちは。NewsPicks Androidエンジニアの sefwgweo です。
今回はタイトルの通り、安全で効率的なログ送信用DataClass運用フローについて紹介します。
コード管理されたログ仕様書
NewsPicks では、モバイル・Web いずれのログも TypeScript から出力されるログ仕様書 を参照しています。
この仕様書は Pull Request ベースで管理 されており、新規追加・変更・削除まで一貫してコードで履歴を追える仕組みになっています。
コード管理によるメリット
- 変更履歴が明確
- 各 OS 間でのログ仕様差分が把握しやすい
- 仕様変更のトレーサビリティが確保できる
(※ログ仕様書の詳細は QA チームが別記事で紹介予定です。)
これまでのログ送信処理追加フロー
以前は、仕様書を参照しながら手作業でログ送信用のDataClassを作成していました。
例えば仕様書に次のようなログ定義があるとします。
LogName: OpenPage parameters: userId: Int pageName: String
上記仕様をもとに以下のようなDataClassを手動で作成します。
data class OpenPageLogEvent( val userId: Int, val pageName: String, )
作成したDataClassは所定のクラスで以下のように利用します。
logSender.send(
OpenPageLogEvent(
userId = 1,
pageName = "カテゴリページ",
)
)
上記例は簡単ですが、実際のログでは10項目以上のパラメータを扱う場合も多く、 そうなると途端に面倒であることがわかると思います。
既存のログ送信用DataClassを自動生成されたJarへ移行する
これまで仕様書をもとに手動でDataClassを作成していた作業は、
仕様書から自動生成されたJar(ビルド済みのログ送信用DataClass集)を
アプリにうまく組み込むことで完全に自動化でき、手作業が不要になります。
Jar移行時の課題
自動生成されたログ送信用DataClassを導入するにあたり、既存の手動実装との乖離が課題でした。
TypeScript で定義したログ仕様書は比較的新しく、一部のログ送信用DataClassでは構造差や命名の不整合がありました。
既存のログ送信用DataClassは大きく分けると次の 4 パターンが存在します。
| ケース | 一致内容 | 対応方針 |
|---|---|---|
| ① | クラス名・パラメータ名・数すべて一致 | 自動生成に置き換え可 |
| ② | クラス名以外すべて一致 | 軽微修正で置き換え可 |
| ③ | OS 間でパラメータ名や数が微妙に異なる | 検討・手動移行 |
| ④ | 構造が複雑かつ確認にコストがかかる | 検討・個別対応 |
まずはケース①と②に焦点を当てて移行を進め、③と④はログ単位で検証しながら段階的に対応することにしました。
運用フロー構築
ログ送信用DataClassは日々更新されるため、ログ仕様書から自動生成されたJar(ビルド済みのログ送信用DataClass集)をAI を用いて 安定的に取り込む仕組み が必要です。
そのため、次の1〜3のような手順を踏むことで運用出来るようにしました。
QAチームによる事前仕分けとアプリ側準備
QAチームが仕様書を元にケース①②のログを分類し、自動生成したJarで安全に置き換え可能なログを特定。
その後、Androidリポジトリでこれらを自動生成したJarに置き換えました。
こうすることで、③④などの未対応ログを並行して手動で置き換えを進めつつ、新規ログは低コストで反映できる状態を作りました。PullRequest連携とJar生成の自動化
上記1により、機械的に安全に置き換えられるものは全てJarで置き換えることができました。
置き換えたログ送信用DataClassに関して問題ないことを動作検証後に、
ログ仕様書リポジトリで変更を反映した PullRequest がマージされるとJar を生成し、
Android リポジトリにラベル付きの Issue を自動作成する仕組みをQA側で作っていただきました。AIによるPull Request作成
こちらでも紹介のあった、専用のラベル付きでIssueを作成するとIssue本文の内容でAIがPullRequestを作る仕組みを使いました。
Issue 内には以下のような内容のプロンプトを実行するClaude Codeのカスタムコマンドが記載されています。
カスタムコマンドは以下のように実行します。
./sync-logspec-jar 20251223.jar
コマンド内では以下のことを行います。
20251223.jarをログ仕様書リポジトリから取得し、所定の場所に置いて `build.gradle.kts` 内の対象部分を取得したJar名に書き換えてください 置き換える前のJarと今回のJarで差分があるファイルを新規追加・更新・削除の3パターンに分類してリストアップしてください。 リストアップしたファイルを以下のルールで仕分けして記載してください 1. 新規追加かつ同名のファイルが既存のコードに存在した場合は、パラメータ名・パラメータ数が一致している場合は既存ファイルを削除し、そうでない場合は「呼び出し元の修正が必要です」と表示してください 2. 更新かつ同名のファイルが既存のコードに存在した場合は「Jarと既存のコードで差分があります。内容を確認し、正しくなるよう修正してください」と表示してください 3. 削除かつ同名のファイルが既存のコードに存在した場合は「Jarと既存のコードで差分があります。内容を確認し、正しくなるよう修正してください」と表示してください 元々記載のあった古いJarファイルを削除し、仕分けするために生成したファイルやディレクトリも削除してください `./gradlew clean build` を実行してビルドエラーがないか確認してください
この仕組みにより、新規のログ追加や軽微な差分確認であればアプリエンジニア以外でもIssue〜PR〜マージまでを完結できるようになりました。
Jar導入効果
- パラメータ名のタイプミスがゼロに
- 実装漏れの削減
- ログ定義から実装までのリードタイム短縮
注意点と今後の改善
いくつかの実装上の課題もありました。
Jar取得の権限問題
ログ仕様書から自動生成されたJarがプライベートリポジトリにあるため、最初はアクセス権が課題でした。
Issue添付も検討しましたがGitHub Actionsから直接添付できなかったため、
現在は仕様書リポジトリをcloneする方法を採用しています。
既存ログ修正への注意喚起
AI は変更内容の正当性を判断できないため、
Jarへの未移行ログに対しての修正や、Jar内のログへの修正が対象のJarに入っていた場合は警告文を表示するようにしました。
まとめ
AI を活用することで、ログ送信用のDataClassの生成〜運用を
「自動化 × 可視化 × 安全移行」 の三軸で実現できました。
とはいえ、完全自動化にはまだ課題が残っています。
今後はケース③④の複雑なログに対しても、安全・効率的な 運用設計を目指していきます。