[PYTHON] La première étape pour se débarrasser des requêtes lentes! J'ai essayé d'avertir Chatwork des requêtes lentes pour RDS pour MySQL à l'aide de Lambda et de l'AWS CLI v2

introduction

Bonjour. En tant que gestionnaire d'infrastructure chez Mikatus Co., Ltd., je suis en charge de la construction, de l'exploitation et de la maintenance de l'infrastructure, etc. centrée sur AWS. Cette fois, j'écrirai sur la notification à Chatwork des requêtes lentes MySQL.

Notre système utilise Amazon RDS pour MySQL, et nous avons utilisé un outil de surveillance pour surveiller l'occurrence des requêtes lentes, mais Chatwork afin que nous puissions apporter des améliorations continues en notifiant en temps réel. J'ai essayé de notifier. De plus, l'autre jour la version préliminaire de l'AWS CLI v2 a été annoncée, donc c'est un gros problème, donc utiliser CLI v2 AWS J'ai essayé de créer une ressource.

À propos de cet article

Cet article explique comment utiliser les paramètres AWS Lambda et les paramètres Amazon CloudWatch Logs à l'aide de l'AWS CLI v2. Il ne couvre pas les étapes détaillées de la fonction d'exportation de journaux Amazon RDS et des paramètres de l'API Chatwork.

Contenu réel de la notification Chatwork

C'est ce dont Chatwork sera enfin informé. Bot publiera le contenu de la requête lente sur le chat de groupe auquel participent les parties concernées. slowquery.png Fondamentalement, la sortie de contenu vers CloudWatch Logs est sortie telle quelle. Étant donné que le journal des requêtes lentes est sorti en UTC uniquement pour l'heure, il est converti en JST pour notification.

Aperçu du traitement

post-slowquery-to-chatwork.png La sortie de RDS vers CloudWatch Logs est la fonction d'exportation de journaux de RDS (https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_LogAccess.Concepts.MySQL.html#USER_LogAccess.MySQLDB.PublishtoCloudWatchLogs ) Est utilisé. CloudWatch Logs utilise des filtres d'abonnement (https://docs.aws.amazon.com/en_jp/AmazonCloudWatch/latest/logs/SubscriptionFilters.html#LambdaFunctionExample) pour envoyer aux fonctions Lambda et écrits en Python. La fonction analyse le message du journal et notifie Chatwork. Le long_query_time du groupe de paramètres RDS peut être utilisé pour contrôler la sortie de requête lente vers CloudWatch Logs, mais le paramètre RDS est relativement lâche et un seuil est défini du côté Lambda afin qu'il puisse être contrôlé. (Cette fois, j'ai défini le RDS long_query_time sur "5" secondes et le seuil Lambda sur "10" secondes.)

Réglages

Je décrirai le contenu de l'ensemble.

Installation de l'AWS CLI v2

Installez l'AWS CLI v2 sur votre mac. Cliquez ici pour la procédure d'installation Veuillez noter qu'il s'agit toujours d'une version préliminaire, veuillez donc ne pas l'utiliser dans un environnement de production.

L'AWS CLI version 2 est fournie pour l'aperçu et l'évaluation des tests. Pour le moment, nous vous recommandons de ne pas l'utiliser dans un environnement de production.

La version suivante a été installée.

$ aws2 --version
aws-cli/2.0.0dev2 Python/3.7.4 Darwin/17.7.0 botocore/2.0.0dev1

Comme impression, CLI v1 a du temps et des efforts au moment de l'introduction en raison de la dépendance de la version de Python, etc. CLI v2 a rendu l'installation beaucoup plus facile sans Python.

Créer un rôle IAM

Définir la valeur

--Nom de rôle

Création de rôle

$ IAM_ROLE_POLICY_DOC="iam-role-policy.json"

#Définir Lambda comme une entité de confiance
$ cat <<EOF > ${IAM_ROLE_POLICY_DOC}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

$ IAM_ROLE_NAME="post-slowquery-to-chatwork-LambdaRole"
$ IAM_POLICY_ARN="arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"

#Créer un rôle IAM
$ aws2 iam create-role \
    --role-name ${IAM_ROLE_NAME} \
    --assume-role-policy-document file://./${IAM_ROLE_POLICY_DOC}

#Obtenez l'ARN du rôle IAM que vous avez créé
$ IAM_ROLE_ARN=`aws2 iam get-role \
    --role-name ${IAM_ROLE_NAME} \
    --query 'Role.Arn' \
    --output text`

#Attacher AWSLambdaBasicExecutionRole au rôle IAM
$ aws2 iam attach-role-policy \
    --role-name ${IAM_ROLE_NAME} \
    --policy-arn ${IAM_POLICY_ARN}

Créer une fonction Lambda

Le runtime utilise python3.7.

code

lambda_function.py


import json
import base64
import gzip
import re
import os
import datetime
import urllib
import urllib.request

LONG_QUERY_TIME = int(os.environ['LONG_QUERY_TIME'])

chatwork_endpoint = "https://api.chatwork.com/v2"
chatwork_apikey = os.environ['chatwork_apikey']
chatwork_roomid = os.environ['chatwork_roomid']
path = "/rooms/{0}/messages".format(chatwork_roomid)

def lambda_handler(event, context):
    print(json.dumps(event))
    #Extrayez le contenu car il est encodé en Base64 et compressé au format gzip.
    log_events = json.loads(gzip.decompress(base64.b64decode(event['awslogs']['data'])))
    db_name = log_events['logStream']
    message = log_events['logEvents'][0]['message']
    #Extraire l'heure de la requête du journal
    query_time = re.search(r'Query_time: ([0-9]+.[0-9]+)', message)

    #Lorsqu'il est supérieur au temps spécifié par la variable d'environnement(10 secondes ou plus cette fois)Notifier
    if LONG_QUERY_TIME < float(query_time.group(1)):
        timestamp = re.search(r'timestamp=([0-9]+);', message)
        #Convertir l'horodatage en heure JST
        date = datetime.datetime.fromtimestamp(int(timestamp.group(1))) + datetime.timedelta(hours=9)
        log_message = re.sub(r'# Time:.*\n', '# Time: %s(JST)\n' % str(date), message)
        post_to_chatwork({'body': '[info][title]%s[/title]%s[/info]' % (db_name, log_message)})

def post_to_chatwork(data=None):
    try:
        if data != None:
            data = urllib.parse.urlencode(data).encode('utf-8')
            headers = {"X-ChatWorkToken": chatwork_apikey}
            req = urllib.request.Request(chatwork_endpoint + path, data=data, headers=headers)
        with urllib.request.urlopen(req) as res:
            print(res.read().decode("utf-8"))
            return
    except urllib.error.HTTPError as e:
        print('Error code: %s' % (e.code))
        sys.exit('post_to_chatwork Error')

Variable d'environnement

Création de fonction Lambda

$ LAMBDA_FUNCTION_NAME="post-slowquery-to-chatwork"
$ LAMBDA_RUNTIME="python3.7"
$ LAMBDA_ZIP_FILE="${LAMBDA_FUNCTION_NAME}.zip"
$ LAMBDA_HANDLER="lambda_function.lambda_handler"
$ LAMBDA_ENV="{\
    LONG_QUERY_TIME=10,\
    chatwork_apikey=XXXXX,\
    chatwork_roomid=XXXXX}"

#Zip le code
$ zip ${LAMBDA_ZIP_FILE} lambda_function.py

#Créer une fonction Lambda
$ aws2 lambda create-function \
    --function-name ${LAMBDA_FUNCTION_NAME} \
    --runtime ${LAMBDA_RUNTIME} \
    --zip-file fileb://${LAMBDA_ZIP_FILE} \
    --handler ${LAMBDA_HANDLER} \
    --environment Variables=${LAMBDA_ENV} \
    --role ${IAM_ROLE_ARN}

Définir le filtre d'abonnement CloudWatch Logs

$ LOG_GROUP_NAME="/aws/rds/instance/[rdsinstance]/slowquery"
$ LOG_FILTER_NAME="LambdaStream_post-slowquery-to-chatwork"
$ LAMBDA_ARN=`aws2 lambda get-function \
    --function-name ${LAMBDA_FUNCTION_NAME} \
    --query 'Configuration.FunctionArn' \
    --output text`
$ LOG_ACTION="lambda:InvokeFunction"
$ LOG_PRINCIPAL="logs.ap-northeast-1.amazonaws.com"
$ SOURCE_ACCOUNT=`aws sts get-caller-identity \
    --query 'Account' \
    --output text`
$ SOURCE_ARN="arn:aws:logs:ap-northeast-1:${SOURCE_ACCOUNT}:log-group:${LOG_GROUP_NAME}:*"

#Donner l'accès à CloudWatch Logs pour exécuter des fonctions
$ aws2 lambda add-permission \
    --function-name ${LAMBDA_FUNCTION_NAME} \
    --statement-id ${LAMBDA_FUNCTION_NAME} \
    --action ${LOG_ACTION} \
    --principal ${LOG_PRINCIPAL} \
    --source-arn ${SOURCE_ARN} \
    --source-account ${SOURCE_ACCOUNT}

#Créez un filtre d'abonnement. Le modèle de filtre est vide("")À
$ aws2 logs put-subscription-filter \
    --log-group-name ${LOG_GROUP_NAME} \
    --filter-name ${LOG_FILTER_NAME} \
    --filter-pattern "" \
    --destination-arn ${LAMBDA_ARN}

Ceci termine les réglages.

à la fin

Cette fois, j'ai utilisé RDS, Lambda et CloudWatch Logs pour notifier les requêtes lentes. Dans le passé, lorsqu'une requête lente se produisait, il était un peu pénible d'aller dans CloudWatch Logs pour voir le journal, il semble donc que la douleur sera atténuée en informant Chatwork de cela. À l'avenir, j'aimerais utiliser pleinement les outils d'analyse des journaux, etc. pour une visualisation plus détaillée, mais j'essaierai de l'implémenter à une autre occasion. En ce qui concerne AWS CLI v2, je n'ai pas profité de beaucoup des avantages liés à son utilisation cette fois, mais je vais l'utiliser activement.

Recommended Posts

La première étape pour se débarrasser des requêtes lentes! J'ai essayé d'avertir Chatwork des requêtes lentes pour RDS pour MySQL à l'aide de Lambda et de l'AWS CLI v2
J'ai essayé de notifier la mise à jour de "Hameln" en utilisant "Beautiful Soup" et "IFTTT"
J'ai essayé d'obtenir une AMI en utilisant AWS Lambda
J'ai essayé de notifier la mise à jour de "Devenir romancier" en utilisant "IFTTT" et "Devenir un romancier API"
J'ai essayé d'obtenir l'index de la liste en utilisant la fonction énumérer
J'ai essayé de créer un traitement par lots sans serveur pour la première fois avec DynamoDB et Step Functions
J'ai essayé d'informer le serveur Zabbix d'une erreur d'exécution de la fonction AWS Lambda
J'ai essayé d'obtenir les résultats de Hachinai en utilisant le traitement d'image
J'ai essayé d'extraire et d'illustrer l'étape de l'histoire à l'aide de COTOHA
J'ai essayé de résumer les paramètres des différentes bases de données de Django (MySQL, PostgreSQL)
J'ai essayé de publier automatiquement sur ChatWork au moment du déploiement avec Fabric et ChatWork Api
J'ai essayé d'obtenir les informations de localisation du bus Odakyu
J'ai essayé d'obtenir les informations du Web en utilisant "Requests" et "lxml"
Une histoire sur l'écriture d'AWS Lambda et de devenir un peu accro aux valeurs par défaut des arguments Python
Je suis devenu horreur quand j'ai essayé de détecter la quantité de fonctionnalités d'un visage animé en utilisant PCA et NMF.
J'ai essayé de prédire les hauts et les bas du cours de clôture du cours de l'action de Guru Navi en utilisant TensorFlow (progression)
J'ai essayé d'obtenir une base de données sur les courses de chevaux en utilisant Pandas
[Python] Comment obtenir le premier et le dernier jour du mois
J'ai essayé d'obtenir une liste de noms AMI en utilisant Boto3
J'ai essayé d'obtenir et d'analyser les données statistiques de la nouvelle Corona avec Python: données de l'Université John's Hopkins
Utilisez AWS lambda pour récupérer les actualités et notifier régulièrement LINE des mises à jour [python]
J'ai essayé de livrer du courrier depuis Node.js et Python en utilisant le service de livraison de courrier (SendGrid) d'IBM Cloud!
J'ai essayé de transformer l'image du visage en utilisant sparse_image_warp de TensorFlow Addons
J'ai essayé de visualiser la tranche d'âge et la distribution des taux d'Atcoder
J'ai essayé d'estimer la similitude de l'intention de la question en utilisant Doc2Vec de gensim
J'ai essayé d'obtenir le code d'authentification de l'API Qiita avec Python.
J'ai essayé de vérifier et d'analyser l'accélération de Python par Cython
J'ai essayé d'obtenir automatiquement le RSS de la chanson la plus populaire de l'iTunes Store
J'ai essayé d'obtenir les informations sur le film de l'API TMDb avec Python
J'ai essayé l'histoire courante de l'utilisation du Deep Learning pour prédire la moyenne Nikkei
En utilisant COTOHA, j'ai essayé de suivre le cours émotionnel de la course aux meros.
J'ai essayé de comprendre attentivement la fonction d'apprentissage dans le réseau de neurones sans utiliser la bibliothèque d'apprentissage automatique (première moitié)
J'ai essayé d'obtenir les informations du site .aspx qui est paginé à l'aide de Selenium IDE aussi sans programmation que possible.
J'ai essayé tensorflow pour la première fois
J'ai essayé de prédire la détérioration de la batterie lithium-ion en utilisant le SDK Qore
[Python] J'ai essayé de juger l'image du membre du groupe d'idols en utilisant Keras
Programmation Python: j'ai essayé d'obtenir (l'exploration) des articles de presse en utilisant Selenium et BeautifulSoup4
J'ai essayé de traiter et de transformer l'image et d'élargir les données pour l'apprentissage automatique
[Introduction à AWS] J'ai essayé de porter une application de conversation et de jouer avec text2speech @ AWS ♪
J'ai essayé d'automatiser le travail de masquage du visage de l'image de coordination pour l'usure
J'ai essayé d'utiliser Twitter Scraper avec AWS Lambda et cela n'a pas fonctionné.