トレタ開発者ブログ

飲食店向け予約/顧客台帳サービス「トレタ」、モバイルオーダー「トレタO/X」などを運営するトレタの開発メンバーによるブログです。

チームで取り組むGo開発:開発体験向上の施策のご紹介

はじめに

こんにちは、サーバーサイドエンジニアの@shiroemonsです。

こちらはトレタAdventCalendar2024 22日目の記事です。

今回は、現在進行中のGoプロジェクトにおけるディレクトリ構成と、開発体験を向上させるために実施した施策について紹介します。

ディレクトリ構成

このディレクトリ構成は、チーム全体で議論を重ね、各メンバーが実装しやすく効率的な形を目指して構築しました。以下がその詳細です。

.
├── cmd # エントリーポイント
│   ├── api # APIサーバー(実際はProject名)
│   └── seeder # 開発環境ダミーデータ生成処理
├── config # 環境変数読み込み
├── db
│   └── migrations # DBマイグレーション
├── docker # Dockerfile
├── docs # ドキュメント
├── firebase # Firebase Emulator Suite設定ファイル
└── internal
    ├── db
    ├── handler # 抽象化先の処理への振り分け
    │   ├── router.go # ルーティング定義
    │   └── v1
    │       └── executor # ユースケース初期化
    ├── http
    │   └── response # レスポンス定義
    ├── infrastructure # 共通インフラ処理
    ├── model # DBモデル定義
    ├── {module} # 抽象化先の名称
    │   ├── infrastructure # 各モジュールのインフラ処理
    │   ├── prepare # 各モジュールの事前処理
    │   ├── values # モジュール内で使用する値オブジェクト
    │   └── {domain} # ビジネスロジックやドメイン処理
    │       ├── repository # DBや外部APIとのやり取り
    │       └── usecase # ユースケース
    ├── errors # エラー定義
    ├── service # 共通サービス処理
    ├── testhelper # テストヘルパー関数
    │   ├── ddl # テスト用DDL
    │   └── testdata # テスト用データ
    ├── util # 汎用的なコード
    └── values # 共通値オブジェクト

開発体験向上の施策

1. 初期データ挿入ツールを作成

プロジェクトの初期段階では、各メンバーが開発環境のデータベースに個別でテストデータを作成し、動作確認を行っていました。しかし、データ構造が複雑であったため、データ作成には多くの手間がかかり、さらにメンバー間で作成するデータにばらつきが生じていました。この状況は動作確認の効率を低下させる一因となっていました。

この問題を解決するために、初期データを効率的に挿入・更新するツール「seeder」を開発しました。このツールはGoで独自に実装され、開発環境において使用することを前提としています。seederは、TSVファイルからデータを読み取り、加工してデータベースにアップサート(挿入・更新)する機能を提供します。

このツールをプロジェクトの早い段階で導入したことで、以下のような効果が得られました。

  1. テストデータの準備が容易に: 手作業で複雑なデータを作成する必要がなくなり、効率的にデータを準備できるようになりました。
  2. 動作確認のハードルが低下: メンバー全員が同一のデータを使用できるため、動作確認が容易になり、プロジェクト全体のスムーズな進行に寄与しました。
  3. 開発効率の向上: テストデータの準備にかかる時間が短縮され、その分のリソースを開発や改善に集中させることができました。

seederの導入により、プロジェクトの開発環境を標準化し、チーム全体の生産性を向上させることができました。これにより、プロジェクトの初期段階からスムーズな開発体制を築くことができ、メンバーの負担軽減にもつながりました。

2. カバレッジレポートの精度向上

seederを導入することで開発効率が大幅に向上した一方、カバレッジレポートの値が大きく下がるという課題が発生しました。この問題の主な原因は以下の2点です。

  1. 開発環境のみで使用するseederがカバレッジ対象に含まれていたこと
  2. テストで使用する自動生成されたモックファイルがカバレッジ計測に影響していたこと

これを解決するために、カバレッジレポートから除外すべきファイルを明確に定義し、それらを簡単にフィルタリングできるスクリプトを作成しました。この取り組みにより、以下の改善を実現しました。

改善内容

  1. 正確なカバレッジレポートの生成
    • 実際のコードカバレッジに影響を与えない部分を除外することで、レポートの精度を向上させました。
  2. 効率的なテスト分析
    • 本来注力すべきコードのカバレッジを明確に把握できるようになり、テストの改善ポイントを特定しやすくなりました。
  3. メンテナンス性の向上
    • 除外対象をスクリプト化することで、プロジェクト全体での運用が容易になりました。

解決策: 除外スクリプトの導入

以下は、カバレッジレポートから不要なファイルを除外するためのスクリプトfilter_coverage.shです。

#!/bin/sh

# 入力引数のチェック
if [ $# -ne 1 ]; then
  echo "Usage: $0 <coverage_file>"
  exit 1
fi

COVERAGE_FILE=$1

# .coverageignore ファイルの存在チェック
if [ ! -f .coverageignore ]; then
  echo ".coverageignore file not found!"
  exit 1
fi

# .coverageignore ファイルを読み込む
IGNORE_FILES=$(cat .coverageignore)

# 一時ファイルを作成
TEMP_FILE="coverage_filtered.out"
cp "$COVERAGE_FILE" "$TEMP_FILE"

# 除外ファイルごとにフィルタリング
for FILE in $IGNORE_FILES
do
    grep -Ev "$FILE" "$TEMP_FILE" > temp.out && mv temp.out "$TEMP_FILE"
done

mv "$TEMP_FILE" "$COVERAGE_FILE"

echo "Filtered coverage report saved to $COVERAGE_FILE"

.coverageignore

以下は、カバレッジレポートから除外すべきファイルを定義する.coverageignoreファイルの例です。

# このファイルには、カバレッジレポートから除外したいファイルパスを記載します。
# 各ファイルパスは新しい行に記載してください。
# ファイルパスには正規表現を使用できます。

# 開発環境用のアプリのため除外
cmd/seeder/main\.go

# 自動生成されたモックファイルを除外
.*_moq\.go

この設定例では、cmd/seeder/main.goは開発環境でのみ使用されるスクリプトであり、本番環境には関係がないためカバレッジレポートから除外しています。また、*_moq.goは自動生成されたモックファイルであり、実際のコードではないためレポートに含める必要がありません。

使い方

  1. カバレッジ計測を実行

     go test -race -shuffle=on ./... -coverprofile=tmp/coverage.out
    
  2. スクリプトで除外ファイルをフィルタリング

     ./filter_coverage.sh tmp/coverage.out
    
  3. カバレッジレポートを確認

     go tool cover -html=tmp/coverage.out
    
    • カバレッジレポートの確認には、octcovの利用がおすすめです。

Makefileで簡易化

手順1と手順2を1つのMakeコマンドとして統合し、さらに手順3も別のMakeコマンドとして設定することで、テスト実行とカバレッジレポートの確認を効率化できます。

test:
    go test -race -shuffle=on ./... -coverprofile=tmp/coverage.out
    ./filter_coverage.sh tmp/coverage.out

coverage-report:
    go tool cover -html=tmp/coverage.out

これにより、以下のコマンドでカバレッジ計測とレポート確認が可能になります。

make test
make coverage-report

3. テストデータの自動生成

データベース関連のテストでは、テストデータの準備が大きな手間となることがあります。特に複雑なデータ構造を扱う場合、手動でのデータ作成には多くの労力が必要であり、チーム内でデータ内容がばらつくリスクも存在していました。しかし、seederを活用することで、効率的にデータを生成し活用できるようになり、これを基盤としてtestfixturesを用いた自動生成の仕組みを導入しました。

github.com

このアプローチにより、以下の効果を実現しています。

  1. テストデータ準備の効率化: 手動での作業を削減し、開発速度を向上。
  2. データの一貫性確保: チーム内で同じデータセットを共有可能に。
  3. 信頼性向上: 自動生成されたデータにより、テストの再現性が高まる。

これにより、テストデータの準備に伴う負担を大幅に軽減し、開発環境を標準化することで、プロジェクト全体の効率を高めました。

解決策: テストデータ自動生成スクリプトの導入

以下は、テストデータを自動生成するためのシェルスクリプトgenerate_testdata.shです。

このスクリプトでは、PostgreSQLデータベースからのデータダンプを利用して、不要なファイルの削除やタイムスタンプの加工も自動化しています。

#!/bin/sh

# testfixtures の dump を実行する
testfixtures --dump -d postgres -c "postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:5432/$POSTGRES_DB?sslmode=disable" -D internal/testhelper/testdata

# 不要なファイルを削除
find ./internal/testhelper/testdata -type f -name "*.yml" -exec grep -q '^\[\]$' {} \; -exec rm {} +
echo "データがないテーブルの不要なファイルを削除しました。"

# created_at と updated_at を RAW=NOW() に置換
find ./internal/testhelper/testdata -type f -name "*.yml" -exec sed -i -E \
  -e 's/created_at: [-0-9T:.Z]+/created_at: RAW=NOW()/g' \
  -e 's/updated_at: [-0-9T:.Z]+/updated_at: RAW=NOW()/g' {} +
echo "created_at と updated_at を RAW=NOW() に置換しました。"

echo "すべての処理が完了しました。"

使い方

  1. スクリプトを実行してテストデータを生成
    • データベース用の環境変数は用意しておく
     ./generate_testdata.sh
    

Makefileで簡易化

手動でスクリプトを実行する手間を減らすため、Makefileに統合することでワンコマンドでの操作が可能になります。

generate-testdata:
    sh ./generate_testdata.sh

実行コマンド:

make generate-testdata

4. git push前の品質チェック

GitHubでコード管理をしており、GitHub Actionsでテストとリントのチェックを行っています。しかし、開発環境上でテストやリントを実行せずにgit pushを行い、CIで失敗して気付くという課題がありました。

この問題を解決するため、Git hooksのpre-pushを活用し、git push前にテストとリントを実行するスクリプトを導入しました。このスクリプトは、開発者がコードをリモートリポジトリに送信する際に自動的に呼び出され、以下を確認します。

  1. テストの成功: コードの変更が既存の機能に影響を与えていないことを保証します。
  2. リントチェック: コーディングスタイルの統一と品質の確保を支援します。

この仕組みにより、コード品質の低下を防ぎ、以下の効果を得られます。

  • 早期の問題発見: テストやリントの失敗を事前に検出でき、手戻りを防ぎます。
  • CI/CDパイプラインの成功率向上: CIでのエラー発生率を削減し、スムーズなデプロイを支援します。
  • チームの効率化: コーディングスタイルの統一により、レビューの効率が向上します。

デメリットとして、pushまでにテストとリントをチェックするため、実行時間がかかり開発スピードが低下する場合があります。しかし、手戻りを防げると考えると十分に有効なアプローチです。

解決策: git hooks pre-push の活用

以下は、git push前にコード品質を確保するためのスクリプト.githooks/pre-pushです。

このスクリプトでは、git pushの実行前にテストとリントを自動的に実行することで、コード品質を向上させるとともに、CI/CDパイプラインでのエラーを未然に防ぐ仕組みを提供しています。

#!/bin/sh

# Dockerのパスを追加
export PATH=$PATH:/usr/local/bin

# テストを実行
echo "🚀 Running tests..."
if ! make test; then
    echo ""
    echo "=========================="
    echo "❌       Tests failed       "
    echo "=========================="
    echo ""
    exit 1
fi

# Lintを実行
echo ""
echo "🔍 Running linter..."
if ! make lint; then
    echo ""
    echo "=========================="
    echo "❌      Linting failed      "
    echo "=========================="
    echo ""
    exit 1
fi

echo ""
echo "=========================="
echo "✅    All checks passed     "
echo "=========================="
echo ""

exit 0
  • make lintでリントのチェックをしています。

使い方

  1. git hooksを設定

     git config --local core.hooksPath .githooks
    
  2. コードの品質チェックを自動化

    git pushコマンド実行時にスクリプトが自動的に呼び出され、テストとリントが実行されます。

5. APIクライアントツール「Bruno」の導入

APIの動作確認を行う際には、従来はPostmanを使用していましたが、チームメンバーごとに確認方法が異なることや、設定に手間がかかるといった課題がありました。さらに、新規メンバーへの情報共有も効率的とは言えませんでした。

これらの課題を解決するため、APIのドキュメント作成と共有にはBrunoを採用しました。Brunoは、Postmanに代わる軽量なAPIクライアントツールであり、特にテキストベースの管理とバージョン管理に優れています。

github.com

導入した理由

  1. ドキュメントとしての扱いやすさ:
    • Brunoではリクエストをテキスト形式(.bru拡張子)で保存できるため、Gitを用いた変更履歴の管理や差分の確認が容易です。
  2. チームでの共有が簡単:
    • .bruファイルをリポジトリに保存して共有することで、新しいメンバーでも簡単に環境をセットアップできます。
  3. 軽量で効率的:
    • PostmanのようなGUIを使用して直感的に操作できるため、APIリクエストの作成や実行が簡単です。また、CLIツールとしても利用できるため、スクリプト化や自動化にも対応しています。

解決策: Brunoを導入する

  1. macOSであれば以下のコマンドで簡単にインストールできます。

     brew install bruno
    
  2. 初期設定は直感的なGUIで構成されており、PostmanなどのAPIクライアントを使用した経験があれば、初めてでも簡単に操作できます。さらに、設定済みのファイルを読み込むだけでセットアップが完了し、すぐに利用を開始できます。

効果

Brunoの特長を活かすことで、APIドキュメントの管理が格段に効率化しました。これにより、チーム全体のAPI開発が迅速かつスムーズに進行し、情報共有の手間を大幅に削減できました。結果として、プロジェクトの生産性と進行速度が向上しました。

まとめ

Goプロジェクトにおける開発体験を向上させるための施策について紹介しました。

開発体験を向上することで、テストカバレッジが20%だったのを70%以上まで引き上げることができました。今回の施策により、特にDBのテストを書くハードルが下がり、テストが書きやすいディレクトリ構造にしたことが大きな要因だと感じています。

この記事が、皆さんの開発に少しでも役立てば幸いです。

おわりに

トレタでは一緒にチームで働いてくれるエンジニアのメンバーやプロダクトマネージャーとして活躍してくれる人を求めています。飲食店の未来をアップデートする事業に興味のある方はお気軽に話を聞きにきてください。

sites.google.com

堅牢なフロントエンド開発を支えるAPI型チェックと防衛的プログラミング

こんにちは、トレタ VPoEの北川です。

フロントエンドアプリケーションで社内外のAPIを利用する際には、セキュリティやデータ整合性の問題、スキーマの不整合、予期しない変更への対応といった数々の課題がつきものです。 こうした課題に対応し、信頼性の高いフロントエンドを構築するために、弊社では防衛的プログラミングと厳密な型チェックを活用しています。これにより、APIとの連携におけるリスクを最小限に抑え、開発の効率と品質を両立させています。

本記事では、防衛的プログラミングの考え方、型チェックを厳密に行う理由、実際の開発現場の例を交えてご紹介します。


API利用におけるセキュリティの重要性

まず、JavaScriptにおける潜在的なセキュリティリスクとして、プロトタイプ汚染が挙げられます。この攻撃手法では、悪意のあるデータを用いてオブジェクトのプロトタイプが不正に変更され、アプリケーション全体に予期しない影響を与える可能性があります。

JavaScriptのオブジェクトはプロトタイプを通じてプロパティやメソッドを継承します。この仕組みを利用して、攻撃者はAPIレスポンスのJSONオブジェクトに特殊なキー(例: __proto__)を含め、プロトタイプを改変します。その結果、アプリケーション全体で動作が予期せぬ形に変更される可能性があります。

具体的なリスクとしては、以下が挙げられます:

  • リモートコード実行:悪意のあるコードがシステム内で実行される。
  • データ改ざん:重要な設定やデータが不正に変更される。
  • サービス停止:予期しないプロパティ変更によるエラーでアプリケーションが動作停止する。

このようなリスクを回避する方法の一つとして、APIレスポンスの厳密な型チェックを行う方法があります。詳細については以下の記事をご参照ください:


厳密な型チェックとスキーマ駆動開発

弊社では、フロントエンドとバックエンドの連携において、スキーマ駆動開発を採用しています。この手法では、開発初期にAPIスキーマを定義し、両チームがそのスキーマに基づいて並行して作業を進めます。

しかし、スキーマ通りに実装したつもりでも、繋ぎ込み時に不具合が発生することがあります。例えば、スキーマ変更の共有漏れや実装ミスによる不整合が挙げられます。このような場合、スキーマに「過不足なく」準拠しているかどうかを検証する仕組みが必要です。

そこで、クライアント側では防衛的プログラミングにより厳密な型チェックを行い、不具合発生時の原因特定とスムーズな修正を実現しています。

新しい機能追加の場合

新機能を既存のシステムに追加する際、非破壊的変更であっても注意が必要です。例えば、新しいフィールドやオプションが追加される場合、クライアント側でそれに対応するロジックが正しく実装されていないと、全体の整合性が崩れる可能性があります。

例えば、あるAPIにオプショナルなフィールドを追加したとします。このフィールドは必須ではないため、既存の仕様を大きく損なうことはありません。しかし、特定の機能やユースケースにおいて、このフィールドが適切に設定されない場合、システム全体の整合性が崩れるリスクが発生します。

この場合は互換性の有無に関わらず、サーバーとクライアント間での正確なコミュニケーションと早期の検知体制が重要です。フロントエンド側で厳密な型チェックを行っていると、必須フィールドでなくてもフィールドが追加されたことでエラーが発生します。 これにより、仕様変更や新機能追加時の対応漏れを防ぎ、システム全体の安定性を保つことができます。

外部APIの場合

一方で、外部APIに対しては、内部APIとは異なる柔軟なアプローチが必要です。外部APIは、提供元によって予告なく変更される可能性があり、必ずしも事前に提供されたスキーマ通りのデータが返ってこない場合もあります。

例えば、ある外部APIを利用する際、仕様と異なるデータが返されることが判明した場合、厳密な型チェックを維持することでかえってエラーが頻発し、開発スピードやシステムの安定性に悪影響を及ぼすことがあります。このような場合、柔軟性を優先したロジックを導入することで、APIの変化に適応しやすくしています。

具体的には、レスポンスデータのバリデーションやエラーハンドリングを強化し、予期しない変更にも耐えられる仕組みを構築しています。


型チェックのデメリットと今後の方針

厳密な型チェックは、多くの場面で開発を効率化し、信頼性を向上させる一方で、デメリットも存在します。特に、リソースが限られているプロダクトでは、型チェックの厳密さが負担となる場合があります。

例えば、開発リソースが縮小されたプロダクトでは、型チェックの更新が滞り、APIの後方互換性を保つことが難しくなる場合があります。一方で、活発に開発が行われているプロダクトでは、厳密な型チェックが問題の早期発見や修正を可能にし、信頼性向上に大きく寄与しています。

そのため、弊社ではプロダクトのフェーズや状況に応じて型チェックの適用範囲を調整し、効率と柔軟性のバランスを図っています。


さいごに

弊社の防衛的プログラミングと型チェックのアプローチをご紹介しました。記載した通りプロジェクトの規模やフェーズにおいて合う合わないがありますが、堅牢で安定したサービス提供に向けた開発の参考にしていただければと思います。

監視業務(オンコール)に必要なこと

こんにちは、トレタVPoEの北川です。 今回はトレタの開発組織で行っている監視業務(オンコール対応)について紹介しようと思います。

監視業務(オンコール対応)

トレタでは飲食店向けにサービスを提供しているため、飲食店の営業時間である深夜や土日祝にもシステムが利用されています。そのためトレタの営業時間外でも安定してサービスを提供できるように監視体制をつくり運用しています。

オンコールとは、システム障害が発生した際にオンコールの担当者が対応できるように待機する業務です。当番の担当者は障害発生時に障害状況の確認や各所への連絡を行います。

トレタではPagerDutyというサービスを使い、事前に定めたSLOの値を超えた場合に待機中の担当者に電話が鳴る仕組みとなっています。オンコール対応は当番制で365日11:00-24:00の時間に対応しています。担当者のルールとしては以下が定められています。

  • 飲酒禁止
  • 通信環境確保
  • 機器携行
  • 覚醒状態であること

簡潔に言うと、呼び出されたときに対応ができる状態であること、となります。それ以外に制約はないので、上記を満たしていれば家で動画を見ててもいいし、外に出掛けても問題はありません。

オンコール対応は業務の一部であるため当番にあたった担当者は会社から手当がつきます。 ただし、開発メンバー全員のオンコール対応への参加は必須にはしていません。プライベートな事情もあるので任意参加としています。

開発組織の方針としては、オンコール対応への参加は推奨としています。開発者は自分たちで作ったサービスの運用に責任を持つべきであり、どういったSLOで運用されるかを理解した上でシステム作りをすべきだからです。

逆に言うと、アラートが鳴らないようにシステム側が万全に対応されていれば、オンコール対応は待機するのみで緊急対応することなく手当を貰うことができます。エンジニアにとって「怠惰」は美徳という考えのもと、深夜や休日を心穏やかに過ごすためにシステムを整えておくモチベーションとして、オンコール対応の仕組みが働くのがこの制度のもう一つの目的です。

監視体制の仕組み化

上記の監視業務を行うには、システム側での監視の仕組み化が必要です。

  1. 障害が発生していることをシステムが検知できること
  2. オンコール担当者が状況を手早く確認できること
  3. オンコール担当者が対応を行える、または適切にエスカレーションできること

これらを構築するために必要なのがSLO / ダッシュボード / 対応マニュアルです。このセットは各アプリケーションや各マイクロサービスごとに整備します。

1. SLOを設定する

まずはシステムに異常がないかを検知するために、メトリクスと閾値を定義します。その閾値となるのが「SLO(Service Level Objective)」です。

監視するメトリクス

クライアントアプリケーションかサーバーかによって異なりますが、以下のメトリクスを設定することが多いです。

  • 稼働率:システムが利用可能な状態になっているか
  • 成功率:システムが正常に稼働しているか
  • 応答速度:システムが期待通りの速さでレスポンスできているか

トレタの場合ではこれらのメトリクスをDatadogのSLOの機能を使って設定を行なっています。そしてDatadogのIntegrationを使い、メトリクスの閾値を超えるとPagerDutyへと通知が行われます。

稼働率

稼働率は主に外形監視を使った死活監視(ヘルスチェック)で計測しています。トレタの場合はMackerelというサービスを使い、事前に設定しているヘルスチェックのエンドポイントに対して定期的にリクエストを行い、エラーとなった場合には通知します。

ヘルスチェックには主に2種類のエンドポイントを設けています

  • システム単体として応答するエンドポイント(/_status_check
  • システム単体および依存するシステムの応答までを確認する、いわゆるDeepHealthCheckを行うエンドポイント(/_health)

Mackerelからは/_health のエンドポイントをリクエストし、エンドポイント内では依存する内部システムのエンドポイント(/_status_check)または外部システムのヘルスチェックエンドポイントへとリクエストを行います。

稼働率の閾値としては、基本的にサービス要求に基づいて設定を行いますが、理論値としては依存するシステムの稼働率が限界値となります。 例えば、CloudRunとCloudSQLを利用しているサーバーの場合、CloudRunの稼働率は99.95%以上であり、CloudSQLの稼働率も99.95%以上です。そのためそのサーバーの稼働率の限界は99.95×99.95の99.90%以上となります。さらにそのサーバーが別サービスを利用している場合にはその稼働率をさらに掛け合わせることになります。 これらは理論値なので、加えてシステム上のダウンタイムなどを加味するとさらに下げた値を現実的な閾値として設定します。

※ 2024年11月時点

成功率

サーバーとしてAPIを提供しているのであれば、成功率は以下で定義できます。

成功率 = 正常に応答したリクエスト数 / 全体のリクエスト数

「正常に応答した」とは、レスポンスのHTTPステータスコード2xx系/3xx系/4xx系のどれかであることとします。

成功率を監視することで、アプリケーションのリリースによりバグが埋めこまれたことや、依存するサービスに障害が起きていることを検知しやすくなります。 成功率の閾値をどうするかは、こちらもアプリケーションやサーバーの特性によります。より事業クリティカルな責務のシステムであれば閾値は高く定義する必要があります。

応答速度

サーバーの応答速度であればAPI Gatewayからレスポンスタイムのメトリクスを取得できます。 クライアントアプリケーションであればページ表示時間になります。 ページ表示時間はトレタの場合はWebページをVercelでホスティングすることが多いので、VercelのSpeed Insightsを使い、FirstContentfulPaint(FCP)LargestContentfulPaint(LCP)を取得することができます。

vercel.com

https://vercel.com/_next/image?url=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Fv1689795055%2Fdocs-assets%2Fstatic%2Fdocs%2Fconcepts%2Fspeed-insights%2Fv2%2Fres-chart-dark.png&w=3840&q=75&dpl=dpl_D3Vd4AcRwGJ3VGKSrKSZDYdQQ5jj

2. Dashboardを作る

ダッシュボードは上記のSLOのメトリクスや、他にもサーバーなどの各種メトリクスを一覧化し、障害が発生した際にどこに異常があるかを見つけやすくするために役立ちます。

ダッシュボードに載せるべきメトリクスというのは一律で定めてはいませんが、サーバーで設定する一般的なメトリクスは主に下記になります。

APIサーバー

  • CPU使用量
  • メモリ使用量

DBサーバー

  • CPU使用量
  • メモリ使用量
  • コネクション数

API Gateway

  • リクエスト数
  • 5xxレスポンス数
  • レイテンシー

3. 対応マニュアル(Runbook)を用意する

「Runbook」と呼ぶことが多いですが、障害発生時にオンコール担当者がどのようにアクションをすればよいかをまとめたドキュメントです。

オンコール担当者がそのアプリケーションやシステムの直接の開発者でない場合でも適切な復旧作業が行えるように、具体的な指示を記載します。

  • 各種アラートの説明
  • 各種アラートがが鳴った時に確認すべきダッシュボードの項目
  • メトリクスに異常がある場合の対応方法

対応方法としてはサーバー台数を増やしたりスペックの変更など、基本的にはGCPやAWSのコンソール上から操作できる内容を手順とあわせて記載します。

それらを行なっても回復しない場合は、最終的には担当開発者へのエスカレーションを行います。エスカレーションの際の連絡先(Slackでのチャンネル、メンバー)もRunbbokに記載が必要です。

さいごに

弊社ではマイクロサービスの構成にした際に、チームが分散されるのと各メンバーの守備範囲が分かれてしまうため、このように体系的な整備を行いました。 チームが拡大した時など、監視体制の検討をはじめた際にぜひ参考にしていただければ幸いです。

© Toreta, Inc.

Powered by Hatena Blog