ZOZOTOWNの監視にモダンなツール(Datadog、PagerDuty、Sentry)を導入した話

f:id:vasilyjp:20190913191134p:plain

こんにちは。カート・決済チームの濱砂です。 今回はZOZOTOWNのサーバーサイドの監視方法や取り組みについて紹介します。

はじめに

現在、ZOZOTOWNでは現行のシステム基盤や開発プロセスをリプレイスするプロジェクトが進んでいます。 リプレイスは順調に進んでいますが、未だ多くは現行のまま動いており、在庫管理を行う基幹システムやバッチ処理なども同様です。 ⽇々多くの機能や運⽤が増え続けているため、現行のシステムもモダンなツールや開発スタイルを取り入れて、日々の業務の効率化やシステムの安定性を向上させる必要があると考えていました。

また、現行のシステムを担当しているエンジニアも今後は新しいリプレイス後の開発に移行する必要があります。 そのため、モダンな開発スタイルや思想を普段の業務の中に取り入れて、忙しい開発の現場でも少しずつキャッチアップする仕組みが必要だと考えていました。

このような背景があり、先ずは監視に焦点を当てて現行の課題を改善しつつ、モダンな開発スタイルを取り入れる取り組みを進めています。

監視の課題

現行のシステムのアプリケーションの監視には独自ツールを使用しています。メトリクス収集 、ロギング、可視化、アラート通知まで基本的にはこのツールを使用して運用しています。 ZOZOTOWN開設当初からシステムの特性を考慮して作り込まれているため、使いやすい点も多く、個人的には何度も障害を乗り越えるために助けてもらったので愛着もあります。

しかし、サービスの規模が大きくなり開発者も増えていく中でいくつか課題が出てきていたため、その課題を改善するための取り組みを行いました。今回はその中からいくつかピックアップして紹介します。

1. 可視化

アプリケーションのエラーログは独自ツールで収集してSQL ServerのDBに保存しています。 ログの内容を見るためのモニター機能はありますが、エラーの件数を集計してグラフ化したり、キャンペーンの登録数などのエラー以外のメトリクスを見たい場合は別の方法で見る必要がありました。 方法としては開発者がDBから直接SQLクエリを発行して抽出を行い、表やグラフを手動で作成していました。それほど時間はかかりませんが、あまり効率的な作業ではありませんでした。

2. アラートの検知

アラートの検知方法は独自ツールのモニター機能を使うかメール通知のため、深夜帯は気付きにくく対応が遅れることもありました。 また、監視業務をSREチームや協力会社の方々に頼ることも多く、自分たちで気付けたとしても監視意識の高い開発者だけに業務が集中してしまう課題もありました。

3. エラーの管理

直近のエラーの内容や件数を見るためのモニター機能はありますが、集計やイシュー管理は手動で行なっています。 また、業務時間外にアラートの通知が来た場合、独自ツールを見るためには社内ネットワークに入る必要があります。 そのため、接続に時間がかかって対応が遅れることや、必要な環境を持ち合わせていない場合は確認が出来ないこともありました。

改善後

f:id:vasilyjp:20190917080020p:plain

1. Datadogで可視化

可視化にはDatadogを導入しています。Datadogは監視に必要な一通りの機能を備えたMonitoring SaaSです。グラフの作りやすさ、見栄えの良さに定評がある、グローバルスタンダードなツールの1つです。

先ず、エラーやメトリクスの情報をDatadogに定期的に送る必要がありました。 そこで、Datadogが提供しているAPIを使い、DBから取得した情報をカスタムメトリクスとしてDatadogに送信するPython Scriptを作成しました。これをDocker Containerの中で1分に1回、バッチ処理としてcronで実行しています。

Sample Script

from datadog import initialize
from datadog import api

# 初期化
options = {
    'api_key':'<DATADOG_API_KEY>',
    'app_key':'<DATADOG_APP_KEY>'
}
initialize(**options)

# パラメータのセット
# 実際はDBから取得した値をセットしています
metric_name = "zozo.custom.error"
value = 1
tags = ['env:prd', 'project:zozo']

# Datadogにメトリクス送信
api.Metric.send(metric=metric_name, points=value, tags=tags)

当初は独自ツールのモニター画面をスクレイピングする仕組みでやっていましたが、メトリクスの追加、変更をする場合はスクリプトの修正が必要という課題がありました。 そのため、各メトリクスの取得条件はDSLにSQLクエリとして記述するようにして、追加や変更が容易に出来るようにしています。

DSL

metrics_name: sql_server.custom.zozo.error
    monitor_sql: |
        SELECT
            COUNT(*) AS total_count
        FROM
            ErrorTable WITH(NOLOCK)
        WHERE
            errorType = 1
    monitor_value_positions:
        - total_count:0

次に収集したメトリクスを使い、DatadogでDashboardを作成して、それを各メンバーが閲覧出来るようにしました。 定期的に見たい情報のDashboardを作成したことで、毎回手動で可視化する必要が無くなりました。

DatadogのDashboard

f:id:vasilyjp:20190913192201p:plain

2. DatadogとPagerDutyでエラー検知

1で収集したメトリクスを使い、DatadogのAlert機能を利用してSlack通知するようにしました。Slackは社内でコミュニケーションハブとして使われていることもあり、エラーの通知に気付きやすくなり、チーム間の情報共有やコラボレーションも円滑に行われるようになりました。

DatadogのSlack通知

f:id:vasilyjp:20190913192227p:plain

また、緊急度の高いインシデントが発生した場合でもすぐ気付けるように、PagerDutyというオンコールシステムを実現するためのSaaSを導入しました。 PagerDutyはオンコールに関する機能が豊富なツールで、インシデント発生時に電話やSMSで通知出来ます。

先ずDatadogとPagerDutyを連携します。その後、オンコールを設定したいDatadogのAlertにPagerDuty用のメンションを設定します。 ここまで設定するとインシデントが発生した場合、PagerDutyの設定の内容に応じてオンコール通知されるようになります。これで深夜帯のアラートも自分たちで気付けるようになりました。

DatadogのAlertの設定

f:id:vasilyjp:20190917083511p:plain

PagerDutyには担当者をカレンダーで設定する機能もあります。また、一次受けの担当者が応答できなかった場合に自動的に二次受け以降の担当者にエスカレーションする、といったようにな機能も備わっています。

これを機に複数人担当の週替わりの運用にしました。スケジュールの管理はPagerDutyで自動行うようになったため、属人的に行ってきた開発者の負担も下げることが出来ました。 初めは慣れない開発者から不安の声もありましたが、フォローしながら少しずつ慣れてもらうことで、監視に対する意識や姿勢も底上げされました。

PagerDutyのスケジュール設定

f:id:vasilyjp:20190913192311p:plain

3. Sentryでエラーの管理

エラーのログの管理にはSentryを導入しています。Sentryはエラーの詳細を収集して可視化出来るサービスです。 対応言語も多く本来であれば導入し易いツールですが、現行ZOZOTOWNのサーバーサイドの使用言語はサポートされておらず、そのまま導入することは出来ませんでした。 そのため、SentryのAPIを使って1と同様に独自ツールでロギングしているエラーの情報をSentryに送信するPython Scriptを作成して定期実行しています。

Sample Script

from raven import Client

#初期化
client = Client('SENTRY_DSN')

# Sentryにエラー情報送信
# 実際はDBから取得した値をセットしています
client.capture('raven.events.Message', message='description', date='errorDt') ,data={
    'tags': {
        'id': 'id',
        'serverId': 'serverId',
        'userAgent': 'userAgent',
        'requestMethod': 'requestMethod',
        'scriptName': 'scriptName',
        'mediatedPath': 'mediatedPath',
        'referer': 'referer',
        'serverName': 'serverName',
        'service': 'service',
        'line': 'line',
        'column': 'column'
    }
})

エラーの情報をSentryに集約したことで、社内ネットワークに入らなくてもエラーの内容が確認出来るようになりました。

Sentryに送られたエラー一覧

f:id:vasilyjp:20190913192328p:plain

今のことろエラーが精査されておらず、件数が膨大なこともあり、全件は送らず閾値を超えた場合のみSentryに送信しています。 全件送るようになれば、Sentryで集計やイシュー管理も出来るので引き続きブラッシュアップしていく予定です。

まとめ

現行のアプリケーションの開発現場にモダンなツールや仕組みを導入したことによって、どのような変化や恩恵があったかについて紹介しました。

ツールは導入して終わりということは無く、日々ブラッシュアップしたり、新しい機能に対応していく必要があります。 また、現行のシステムを改善するには作りや課題を深く理解して、そのシステムに合うやり方で導入する必要があるため、時間も掛かり何かと苦労することも多いです。 しかし、試行錯誤しながら地道に改善に取り組むことはサービスを良くしていくためには必要なことで、リプレイス後もそれは変わらないと考えています。

現行のシステムを深く理解して本質的な改善を行っていくためにも、現行のシステムやそれを支えてきた方々へのリスペクトの気持ちを忘れず、引き続きこのような取り組みを続けていきます。

最後に

ZOZOテクノロジーズでは、一緒にサービスを作り上げてくれる方を募集しています。 ご興味のある方は、こちらからぜひご応募ください。

カテゴリー