スマートニュースの
世界展開を支えるログ解析基盤
坂本卓巳
スマートニュース株式会社
スマートニュース公式キャラ
地球くん
About Me
• 坂本卓巳
• github/twitter: @takus
• スマートニュース株式会社
• インフラ中心にサービスの下回りの面倒をみている
• 2014 年 08 月 にジョイン
• ログ解析系の仕事はそのタイミングではじめた
ML-based News App
Number of Downloads
米国版リリース
国内で広告事業を開始
インターナショナル版リリース
1,000,000 MAU in US
https://www.techinasia.com/smartnews-us-1m-monthly-active-users/
http://aws.amazon.com/jp/solutions/case-studies/smartnews/
一行のログの向こうには、
一人のユーザがいる
http://ihara2525.tumblr.com/post/17029509298
スマートニュースの場合
KPI ダッシュボード
たとえば A/B テストの結果を確認してサービス改善
ログ祭り
社長∼アプリエンジニア∼サーバエンジニアで開発合宿
全員でログの問題を議論、改善に取り組むハッカソン
ログ解析基盤の話
Collect Process VisualizeStore
アプリでログを取得
API サーバで受信
ストレージに永続化
前処理 (ETL)
集計
BI ツールなどで可視化
Data Pipelines
アプリから送信されるログ
• ユーザの行動
• ニュース記事を読んだ
• ユーザの行動に基づくプロパティ
• 記事の URL、記事の滞在時間
• そのほか、デバイスでしか知り得ない情報
• デバイス情報、OS のバージョン、アプリのバージョン
JSON ログの例
{
"event" : "viewArticle",
"timestamp" : "2014-11-28 12:45:14",
"properties" : {
"userId" : 1224434,
"os" : "android",
"country" : "Japan",
"url" : "http://www.example.com/",
"duration" : 224.8
}
}
アプリからサーバへの送信
• バッファリングしてバルク送信
• クックパッドさんの Puree (※) 的な
• オフライン時はオンラインになったタイミングで送信
• 必要に応じてサーバ側で情報を付与
• A/B テストの参加状況など
※ http://techlife.cookpad.com/entry/2014/11/25/132008
Collect Process VisualizeStore
アプリでログを取得
API サーバで受信
ストレージに永続化
前処理 (ETL)
集計
BI ツールなどで可視化
Data Pipelines
会社の状況や技術動向によって変化
時系列で振り返ってみる
(※入社以前の話は伝聞です)
時期: 2012.12 2013.03
規模: 3 名
状況:
- 2012.12 に iOS 版リリース
- 色々な意味で多くの反響
当時の課題と解決策
• Google Analytics だけでは見たい KPI がみれない
• 某ゲーム会社のコホートが見れる KPI ツールが欲しい
• KPI ツールを自作
• 時代は Fluentd + MongoDB ですよ(キリッ
• フロントエンドは Rails アプリ
Process
Visualize
Store 直近数日分を MongoDB に保存
MongoDB の MapReduce で前処理
Ruby で集計して、Mongo に保存
Rails 製の可視化ツール
時期: 2013.04 2014.07
規模: 12 名
状況:
- 国内でインストール数が増加
- アドホック解析の需要が高まり始める
当時の課題と解決策
• 処理時間の増加 / アドホック解析しにくい
• MongoDB の MapReduce の処理時間が延び続ける
• アドホック解析するにも MongoDB は直近のデータのみ
• EMR / Redshift の導入
• S3 にすべてのログを永続化、前処理を EMR に移行
• 別システムとして Redshift を導入
Process
Visualize
Store 全てのログを S3 に保存
EMR (mrjob) での前処理
Ruby で集計して、Mongo に保存
Rails 製の可視化ツール
Redshift はタブローなどで可視化
時期: 2014.08 2014.10
規模: 30 名
状況:
- 米国版をリリース
- 広告チーム立ち上げ
当時の課題と解決策
• 集計項目が増えて破綻しかかる
• OS 毎、国毎、言語毎、タイムゾーン毎に集計が必要
• 並列化できてない Ruby 部分もボトルネックに
• MongoDB と Redshift のスキーマ乖離問題
• Hive/Presto の検証と導入
• 直近の問題を解決しつつ、知見を貯めるフェーズ
• 次のフェーズへのよいステップになった
Process
Visualize
Store 全てのログを S3 に保存
EMR (mrjob) + Hive で前処理
Presto で集計し、結果を MongoDB へ
自作の Rails 製可視化ツール
時期: 2014.11
規模: 50 名
状況:
- 米国での採用が増え始める
- インターナショナル版のリリース
当時の課題と解決策 1
• ログ解析系のタスクが特定の個人に集中
• 非エンジニアにツラい。サーバに SSH?MongoDB?
• Rails の可視化ツールのメンテをできる人が少ない
• ビューの追加依頼についていけない
• さらにアドホックな機能追加でメンテコストが増大
• 皆が自由にデータにアクセスできるようにしたい
• Chartio や Shib などのツールを導入
• ETL 処理が複雑化
• 直列に実行すると処理時間が増加
• 並列に実行するとフローが複雑化、再実行が職人芸に
• ジョブフローマネージャーの導入
• 依存定義や、リトライ、SLA などの面倒みてくれる
• いくつか試したが Azkaban に落ち着く
当時の課題と解決策 2
Process
Visualize
Store 全てのログを S3 に保存
Hive on EMR で前処理
バッチジョブを Azkaban 管理
集計は Presto
Chartio で各個人がログを可視化
Shib でクエリ実行結果を共有
System Architecture
Data Schema
• スタースキーマ
• データウェアハウスに利用される最も単純なスキーマ
• Facts
• ユーザの行動ログ
• Dimensions
• ユーザの属性 (OS、国、A/B Test 参加情報など)
Data Schema
user_id action url
1 readArticle http://example.com/1
2 readArticle http://example.com/2
3 readArticle http://example.com/3
Actions
user_id os
1 ios
2 android
3 ios
User OS
user_id country
1 US
2 JP
3 GB
User Location
user_id identifier behavior
1 tutorial_04 A
2 tutorial_04 B
3 tutorial_04 A
User A/B Test
user_id version
1 2.2.1
2 1.9.8
3 2.2.0
User App Version
SELECT
date,
behavior,
count(distinct ac.user_id) as DAU,
count_if(action='readArticle') as DPV
FROM actions facts
LEFT JOIN abtest_users dimensions ON facts.user_id = dimensions.user_id
WHERE
definition = 41 AND
date BETWEEN '2015-01-01' AND '2015-01-31'
GROUP BY date, behavior
ORDER BY date, behavior
;
A/B テスト別の KPI を求める
API
Server
Archive
Bucket
Analysis
Bucket
ETL
Cluster
Analysis
Cluster
Data Flow
BI Tool
User
WebUI
設計思想 1
• 開発者・非エンジニア・経営者
• 誰もが簡単に大規模なデータセットにアクセスできる
• SQL (HQL) を共通言語にする
• データを見たい人が見たい形で可視化
• 必要であれば簡単にドリルダウンしていける
• 運用者
• ログを専任でやる人はいない、運用コスト最小化
設計思想 2
• ストレージ層とアプリケーションは分離しておく
• re:Invent 2014 で Aurora や Netflix のセッション
• 筋のよい設計だと感じた
• クラウドらしい、様々なメリット
• 必要に応じて柔軟にキャパシティ追加が可能
• いつ落ちてもいいのでスポットインスタンスを活用できる
• ミドルウェアのバージョンアップ検証が簡易に
(SDD415) NEW LAUNCH: Amazon Aurora: Amazon’s New Relational Database Engine | AWS re:Invent 2014
(BDT403) Netflix's Next Generation Big Data Platform | AWS re:Invent 2014
API
Server
Archive
Bucket
Analysis
Bucket
ETL
Cluster
Analysis
Cluster
ログの保存
BI Tool
User
WebUI
• 各サーバから Fluentd で直接 S3 にアップロード
• date と hour で prefix を切るのがオススメ
ログの保存
API
Server
Archive
Bucket
保存先の例:
s3://smartnews/log/production/raw_actions/date=2015-03-22/hour=00/
API
Server
Archive
Bucket
Analysis
Bucket
ETL
Cluster
Analysis
Cluster
データの前処理
BI Tool
User
WebUI
Hive
• EMR で Hive のクラスタを立ち上げる
• External Table にパーティションを追加していく
• Facts
• S3 に保存されてる生ログのパスを指定するだけ
• Dimensions
• RDS の table dump を S3 に置き、そのパスを指定
• カラムナストレージに変換して S3 に保存
• ORC/Parquet などのデータ解析に適したフォーマット
Hive クラスタの起動
• AWS CLI 経由で起動する
• インスタンスのタイプ・数などを JSON で定義
• Bootstrap actions でミドルウェアのセットアップ
• Hive の Metastore の設定など
• Python + AWS EMR 貧者のログ集計(※) が参考になる
※ http://www.slideshare.net/akirachiku/python-hive-on-emr
Hive クラスタの起動
Old Hive Cluster
New Hive Cluster
User A
User B
MetaStore
Archive
Bucket
Analysis
Bucket
launch
launch
read
write
Hive の Metastore は RDS で共有している
新しくクラスタを起動してS3 の書き込み先を変更すれば検証が容易
read
write
Hive による ETL
-- External Table として、Fluentd のログ形式を定義
CREATE EXTERNAL TABLE IF NOT EXISTS raw_actions (
timestamp STRING,
tag STRING,
data STRING
)
PARTITIONED BY ( date STRING, hour STRING )
ROW FORMAT DELIMITED FIELDS TERMINATED BY 't'
LOCATION 's3://smartnews/log/production/raw_actions/';
;
-- パーティションを追加する
ALTER TABLE raw_actions ADD IF NOT EXISTS PARTITION (`date`='${DATE}', `hour`='${HOUR}')
LOCATION 's3://smartnews/log/production/raw_actions/date=${DATE}/hour=${HOUR}';
Fluentd のログを読むためのテーブルを定義し、パーティションを追加
Hive による ETL
-- カラムナストレージの External Table を定義
CREATE EXTERNAL TABLE IF NOT EXISTS orc_actions (
timestamp INT,
user_id INT,
os STRING,
country STRING,
action STRING,
data STRING
)
PARTITIONED BY ( date STRING, hour STRING )
STORED AS ORC
LOCATION 's3://smartnews/log/production/raw_actions/';
TBLPROPERTIES ("orc.compress"="SNAPPY");
カラムナストレージのテーブルを定義
-- カラムナストレージの External Table にインポート
INSERT OVERWRITE TABLE orc_actions
PARTITION (`date` = '${DATE}', `hour` = '${HOUR}')
SELECT
user_id, timestamp, COALESCE(os, "undefined"), COALESCE(country, "undefined"), action
modify_json(data, 'unnecessary1', 'unnecessary2')
FROM raw_actions
LATERAL VIEW json_tuple(
raw_actions.json, 'userId', 'timestamp', 'platform', 'country', 'action', 'data'
) a as user_id, timestamp, os, country, action, data
WHERE date = '${DATE}' and hour = '${HOUR}'
ORDER BY os,country, action, user_id;
Hive による ETL
json_tuple 関数や explode 関数などで JSON を展開する
自作 UDF で、特定フィールドの JSON から不要なフィールド削除
Azkaban
• ジョブフロー管理ツール
• LinkedInが OSS として公開している
• 主な機能
• 依存定義、依存関係の可視化
• ジョブの定期実行、アドホック実行、リトライ
• 成功・失敗時にメール通知
Azkaban のいいところ
• ジョブ管理がしやすい
• ジョブの依存関係とどこまで完了したかの可視化
• ジョブをコードとして管理
• タイムアウト (SLA) 設定 (例:1時間で終了しなければ通知)
type=command
command=hive-wrapper -d 2015-02-02 -q query_c
dependencies=query_a, query_b
ジョブ定義ファイルの例
ジョブの依存関係の例
User Features
Raw table
Intermediate
Table
緑は成功済み、赤は失敗しているので再実行が必要
再実行が必要なジョブだけ有効にして再実行が可能
Azkaban を使う上での工夫
• AmazonEMR と Azkaban にそれぞれ制約
• EMR のステップは常に直列に実行される
• Azkaban の Executor は 1 台しか持てない
• Beeline から Thrift 経由でジョブを実行
• 依存解決した JAR を Executor に配置
• EMR のタグからホスト名を解決してクラスタにアクセス
Azkaban を使う上での工夫
Production
Hive Cluster
Development
Hive Cluster
User A
User B
Archive
Bucket
Analysis
Bucket
read
write
submit
job
register
job
beeline
azkaban
Temp
Hive Cluster
EMR のタグから beeline に渡すホスト名を求めて実行
API
Server
Archive
Bucket
Analysis
Bucket
ETL
Cluster
Analysis
Cluster
ログ解析用クラスタ
BI Tool
User
Web UI
Presto
• 分散 SQL クエリ実行エンジン
• Facebook が OSS として公開
• ANSI SQLに準拠し、一般的な集計関数などをサポート
• Presto はストレージを持たない
• 様々なデータソース (Hive、MySQL) にアクセス
• 詳細は Treasure Data 様のスライドにて
Presto: Interactive SQL Query Engine for Big Data | Hadoop Conference in Japan 2014
Presto のいいところ
• クエリの実行が高速
• 数十億行のスキャンに数秒∼数十秒
• 数十億 x 一千万 くらいの JOIN しても 数十秒∼数分
• チューニングやノード増やせばさらに高速化できそう
Presto のいいところ
• 複数データソースを JOIN できる
• 例1: Hive のログと MySQL のマスタ
• MySQL はフルスキャン走るので注意
• 例2: アプリの Hive のログとアドの Hive のログ
• 疎結合なシステム同士のログを繋ぎ込める
• Amazon Aurora とも JOIN できるはず
• 検証したわけではない
Presto のいいところ
• 運用がカンタン
• AWS が EMR の bootstrap action を提供
• https://github.com/awslabs/emr-bootstrap-actions
• 社内向けに一部拡張している
• Blue-Green Deployment でバージョンアップ
• 新バージョンが出たら新たにクラスタ起動
• 検証して問題なければ、DNS / Tag を切り替える
API
Server
Archive
Bucket
Analysis
Bucket
ETL
Cluster
Analysis
Cluster
可視化
BI Tool
User
Web UI
Chartio
• 様々なデータソースを組み合わせてダッシュボード作れる
• バックエンドが切り替えられる Kibana のイメージ
• MySQL、Redshift、Google Analytics, BigQuery, etc...
• Presto は Prestogres or ssh tunnel で接続
• 可視化周りの仕事を楽にしてくれる
• ドラッグ & ドロップ / SQL でチャート作成
• UI もキレイで毎日見る気が起きる
ダッシュボードの作り方
1. クエリを組み立てる
(ドラッグ&ドロップ / SQL 直接入力)
2. データをプレビューしながら整形
(絞り込み、並び替え、カラム追加)
3. 様々な形式で可視化
(表、円グラフ、棒グラフなど)
ダッシュボードの例
Chartio のいいところ
• フロントエンドの細かい作り込みが不要に
• バックエンドを作れば、後は可視化したい人に任せる
• SQL の範囲であれば、かなり色々とできる
• Categorical Dropdown で属性を絞り込んでいける
• 全体集計
• 特定の OS x 特定の国 x 特定のチャンネル
• データを色んな角度から見ていきやすい
様々な属性で絞り込む例
英国で iOS の bbc.co.uk の記事のランキングどうなってる?
例1: メディアリレーションの人の依頼
様々な属性で絞り込む例
カリフォルニアで実施中の、ある A/B テストの状況どうだっけ?
iPhone 6 での調子が悪いみたいなのだけど確認できる?
例2: アプリ開発者の依頼
re:Invent 2014 で交流
ログ解析基盤の改善による効果
• 様々な軸で絞り込みをした上でのメトリクス可視化
• 国別、OS 別、チャンネル別、デバイス別...
• A/B Test の結果を確認
• 記事選択アルゴリズム、チュートリアル改善
• 今まで見れてなかった指標が見れるように
• 大規模データセット向けの機械学習ライブラリの利用
• Hivemall や SparkMLlib など
Google BigQuery の話
• かなり破壊的なテクノロジー
• 数千台規模のコンテナでログをフルスキャン
• Hive で持ってるログを BQ にも送って検証中
• S3 → GCS → BQ にロード (gsutil sync)
• ストレージとクエリ課金に関しては安い
• KPI 集計するだけならコレだけでよいのではという印象
全部 BQ 任せでいいのか?
• 何を自分たちでやり、何を他人に任せるのか意識する
• 自分でやれば経験や知識が蓄積されていく
• 他人に任せると学びは少ないがコストは下がる
• 僕らにとってはデータを扱う技術は大事にすべき要素
• ある程度は自分たちでも追いかけるべき
• 結果として Hivemall や SparkMLlib が利用できたり
• でも、BQ が活用できる部分は積極的に使っていく予定
• UDF も出るというウワサ
今後の展望など
• さらなる利用ケースの拡大
• 様々なログを様々な軸で切って解析し、サービス改善
• 例えばアプリのバージョン別のレスポンスタイム確認とか
• サービスの異常検知
• 特定の OS x 特定のバージョンだけレスポンス遅いとか
• 機械学習のエキスパートが多い、恵まれた環境
まとめ
• スマートニュースのログ解析基盤の過去と現在
• 会社の規模や状況に応じて進化してきた
• AWS、OSS、X as a Service の力を借りて改善
• EMR/Fluentd/Hive/Azkaban/Presto/Chartio ...
• よりスマートなニュースアプリに進化していく予定
• お手伝いいただける方、絶賛募集中です!!!
告知
https://atnd.org/events/64096
SmartNews TGIF 04/17
• SmartNews TGIF とは?
• 外部の人を招待してオフィスで交流会
• 美味しいケータリングとアルコールが出ます(無料!)
• 興味がある方は @takus まで連絡ください
• 今日の話をもっと詳しく聞きたい
• アプリで A/B テストをがりがり回す話が聞きたい
• 広告サイドのログや A/B テストの話が聞きたい

スマートニュースの世界展開を支えるログ解析基盤