⏱️

RDSにてスロークエリーログの分析レポートを定期的取得してGitHubで管理する

2022/06/05に公開

はじめに

DBの負荷高騰時に、毎回pt-query-digestをローカルから実行して分析していたのですが、取得と共有が面倒だったので、GitHubActionsを使うことでサクッと解決しました。

pt-query-digestとは?

pt-query-digestは最近発売した「達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践」でも紹介されているスロークエリーログの分析ツールです。
https://www.percona.com/doc/percona-toolkit/LATEST/pt-query-digest.html

前提

スロークエリーの取得が有効になっていること

当然ですがスロークエリーログを元に分析するため、ログの取得は有効にしている必要があります。
未設定の場合は以下のリンクなどを参考に設定してください。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/USER_LogAccess.MySQL.LogFileSize.html#USER_LogAccess.MySQL.Generallog

AWS OIDCにてGitHubActionsの設定が完了していること

スロークエリーはCloudWatchLogsに保存されているため、GitHubActionsからAWSのリソースへのアクセス権限を設定する必要があります。
OIDC経由での権限付与の方式でGitHubActionsを作成しているため、事前に以下の設定を行う必要があります。
https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services

分析頻度は毎時で直近の時間帯を取得

毎時0分でのスケジュール実行で、実行された時間の1時間前の00分〜59分をスロークエリーログの取得範囲とするとこで、毎時でのレポートを生成しています。
分析頻度を変更したい方は、GitHubActionsのschedule設定と、スロークエリーログ取得部分をよきに変更してください。(突貫なので汎用的には作ってないです。)

設定

GitHubActions

name: Slow Query Summary

permissions:
  id-token: write
  contents: write
  issues: write
  pull-requests: write
  
on:
  schedule:
    - cron:  '0 * * * *'
  workflow_dispatch:

env:
    ## スロークエリーログが保存されているロググループ名を設定
  LOG_GROUP: <CloudWatchLogGroupName> 

jobs:
  pt-query-digest:
    runs-on: ubuntu-latest
    strategy:
      matrix:
	## ロググループ内のストリーム名を設定 複数台構成の場合は複数指定(ライターとリーダーの両方を取得する想定)
        db: [<CloudWatchLogStreamName1>, <CloudWatchLogStreamName2>]
        
    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-region: ap-northeast-1
	## OIDC経由のアクセスするIAMロールARNを設定
        role-to-assume: arn:aws:iam::**********:role/<GitHubActionsOIDCARoleName>
        role-session-name: ${{ github.event.repository.name }}

    - name: install pt-query-digest
      run: |
        sudo apt-get install percona-toolkit

    - name: make slow query report
      env:
        LOG_GROUP: ${{ env.LOG_GROUP }}
        LOG_STREAM: ${{ matrix.db }}
      run: |
        report_date=$(TZ=JST-9 date '+%Y%m%d' --date '1 hour ago')
        report_dir="${report_date}/${LOG_STREAM}"
        if [ ! -d ${report_dir} ];then mkdir -p $report_dir; fi
        cd $report_dir
        start=$(TZ=JST-9 date '+%Y-%m-%d %H:00:00' --date '1 hour ago')
        end=$(TZ=JST-9 date '+%Y-%m-%d %H:59:59' --date '1 hour ago')
        starttime=$(expr `TZ=JST-9 date --date "$start" +%s` \* 1000)
        endtime=$(expr `TZ=JST-9 date --date "$end" +%s` \* 1000)
        echo "starttime: ${starttime}, endtime ${endtime}"
        aws logs get-log-events \
        --log-group-name ${LOG_GROUP} \
        --log-stream-name ${LOG_STREAM} \
        --start-time ${starttime} \
        --end-time ${endtime} \
        --query 'events[].message' \
        |jq -r '.[]' \
        | pt-query-digest > $(TZ=JST-9 date '+%H00' --date '1 hour ago').txt

    - name: git push files
      run: |
        git config --local user.email "action@github.com"
        git config --local user.name "GitHub Action"
        git add .
        git commit -m "Add changes"
        git pull --rebase
        git push

実行

実行すると以下のように日付ディレクトリ配下で、リーダーとライターそれぞれのインスタンスのスロークエリーの分析結果が時間帯毎にGitHubリポジトリに保存されます。

├── 20220605
│   ├── <CloudWatchLogStreamName1>
│   │   ├── 0800.txt
│   │   ├── 0900.txt
│   │   ├── 1000.txt
│   │   ├── 1100.txt
│   │   ├── 1200.txt
│   │   └── 1300.txt
│   └── <CloudWatchLogStreamName2>
│       ├── 0800.txt
│       ├── 0900.txt
│       ├── 1000.txt
│       ├── 1100.txt
│       ├── 1200.txt
│       └── 1300.txt

まとめ

GitHubActionsを利用することでサクッと作ってみました!

この辺の稼働レポート系はS3に集約して分析とか、Lambda使っていい感じに整形してSlack通知とか、いろいろ手段があるのですが、やろうとするとAWSのリソースの作成やLambdaコードの作成など手間が多いです。

GitHubActionsのスケジュール機能とデータの保存場所をGitHubリポジトリそのものにすることで、追加のリソース作成などせずGitHubで全てが完結するので、最近はよく利用しています。

この情報がだれかのトイルの削減に役立てば幸いです!

Discussion