Hallo. Als Infrastrukturmanager bei Mikatus Co., Ltd. bin ich verantwortlich für den Bau, den Betrieb und die Wartung der Infrastruktur usw. mit Schwerpunkt AWS. Dieses Mal werde ich über das Benachrichtigen von Chatwork über langsame MySQL-Abfragen schreiben.
Unser System verwendet Amazon RDS für MySQL und wir haben ein Überwachungstool verwendet, um das Auftreten langsamer Abfragen zu überwachen, aber Chatwork, damit wir durch Benachrichtigungen in Echtzeit kontinuierliche Verbesserungen erzielen können. Ich habe versucht zu benachrichtigen. Neulich AWS CLI v2-Vorschau-Version wurde angekündigt, also ist es eine große Sache, also CLI v2 AWS zu verwenden Ich habe versucht, eine Ressource zu erstellen.
Dieser Artikel enthält Schritte zum Arbeiten mit AWS Lambda-Einstellungen und Amazon CloudWatch-Protokolleinstellungen mit AWS CLI v2. Die detaillierten Schritte der Amazon RDS-Protokollexportfunktion und der Chatwork-API-Einstellungen werden nicht behandelt.
Dies wird Chatwork schließlich mitgeteilt. Bot veröffentlicht den Inhalt der langsamen Abfrage im Gruppenchat, an dem die betroffenen Parteien teilnehmen. Grundsätzlich wird die Ausgabe von Inhalten in CloudWatch-Protokolle unverändert ausgegeben. Da das langsame Abfrageprotokoll nur für die Zeit in UTC ausgegeben wird, wird es zur Benachrichtigung in JST konvertiert.
Die Ausgabe von RDS in CloudWatch-Protokolle erfolgt über RDS Log Export Function ) Wird genutzt. CloudWatch Logs verwendet Abonnementfilter (https://docs.aws.amazon.com/de_jp/AmazonCloudWatch/latest/logs/SubscriptionFilters.html#LambdaFunctionExample), um sie an Lambda-Funktionen zu senden und in Python zu schreiben. Die Funktion analysiert die Protokollnachricht und benachrichtigt Chatwork. Sie können die langsame Abfrageausgabe an CloudWatch-Protokolle mit der long_query_time der RDS-Parametergruppe steuern. Die RDS-Einstellung ist jedoch relativ locker und die Lambda-Seite legt einen Schwellenwert fest, damit sie gesteuert werden kann. (Dieses Mal habe ich die RDS long_query_time auf "5" Sekunden und den Lambda-Schwellenwert auf "10" Sekunden gesetzt.)
Ich werde den Inhalt des Sets beschreiben.
Installieren Sie AWS CLI v2 auf Ihrem Mac. Klicken Sie hier, um den Installationsvorgang zu starten Bitte beachten Sie, dass es sich immer noch um eine Vorschau-Version handelt. Verwenden Sie sie daher nicht in einer Produktionsumgebung.
AWS CLI Version 2 wird für die Testvorschau und -auswertung bereitgestellt. Derzeit empfehlen wir, es nicht in einer Produktionsumgebung zu verwenden.
Die folgende Version wurde installiert.
$ aws2 --version
aws-cli/2.0.0dev2 Python/3.7.4 Darwin/17.7.0 botocore/2.0.0dev1
Als Eindruck hat CLI v1 eine gewisse Abhängigkeit von der Python-Version, daher dauerte die Einführung einige Zeit, aber CLI v2 hat die Installation ohne Python erheblich vereinfacht.
--Rollenname
$ IAM_ROLE_POLICY_DOC="iam-role-policy.json"
#Legen Sie Lambda als vertrauenswürdige Entität fest
$ 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"
#Erstellen Sie eine IAM-Rolle
$ aws2 iam create-role \
--role-name ${IAM_ROLE_NAME} \
--assume-role-policy-document file://./${IAM_ROLE_POLICY_DOC}
#Rufen Sie die ARN der von Ihnen erstellten IAM-Rolle ab
$ IAM_ROLE_ARN=`aws2 iam get-role \
--role-name ${IAM_ROLE_NAME} \
--query 'Role.Arn' \
--output text`
#Fügen Sie der IAM-Rolle AWSLambdaBasicExecutionRole hinzu
$ aws2 iam attach-role-policy \
--role-name ${IAM_ROLE_NAME} \
--policy-arn ${IAM_POLICY_ARN}
Die Laufzeit verwendet python3.7.
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))
#Extrahieren Sie den Inhalt, da er in Base64 codiert und im gzip-Format komprimiert ist.
log_events = json.loads(gzip.decompress(base64.b64decode(event['awslogs']['data'])))
db_name = log_events['logStream']
message = log_events['logEvents'][0]['message']
#Extrahieren Sie die Abfragezeit aus dem Protokoll
query_time = re.search(r'Query_time: ([0-9]+.[0-9]+)', message)
#Wenn es größer als die von der Umgebungsvariablen angegebene Zeit ist(Diesmal 10 Sekunden oder länger)Benachrichtigen
if LONG_QUERY_TIME < float(query_time.group(1)):
timestamp = re.search(r'timestamp=([0-9]+);', message)
#Zeitstempel in JST-Zeit konvertieren
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')
$ 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}"
#Zippen Sie den Code
$ zip ${LAMBDA_ZIP_FILE} lambda_function.py
#Erstellen Sie eine Lambda-Funktion
$ 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}
$ 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}:*"
#Gewähren Sie CloudWatch-Protokollen Zugriff zum Ausführen von Funktionen
$ 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}
#Erstellen Sie einen Abonnementfilter. Das Filtermuster ist leer("")Zu
$ aws2 logs put-subscription-filter \
--log-group-name ${LOG_GROUP_NAME} \
--filter-name ${LOG_FILTER_NAME} \
--filter-pattern "" \
--destination-arn ${LAMBDA_ARN}
Damit sind die Einstellungen abgeschlossen.
Dieses Mal habe ich RDS-, Lambda- und CloudWatch-Protokolle verwendet, um langsame Abfragen zu benachrichtigen. In der Vergangenheit war es bei einer langsamen Abfrage etwas mühsam, zu CloudWatch-Protokollen zu gehen, um das Protokoll anzuzeigen. Es scheint also, dass die Schmerzen gelindert werden, wenn Chatwork darüber informiert wird. In Zukunft möchte ich die Protokollanalysetools usw. für eine detailliertere Visualisierung vollständig nutzen, werde aber versuchen, sie bei einer anderen Gelegenheit zu implementieren. Was AWS CLI v2 betrifft, habe ich dieses Mal nicht viele Vorteile im Rahmen der Verwendung genossen, aber ich werde es aktiv nutzen.