mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Metrics lambda
This commit is contained in:
parent
112a009b91
commit
0085e5653a
13
tests/ci/metrics_lambda/Dockerfile
Normal file
13
tests/ci/metrics_lambda/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM public.ecr.aws/lambda/python:3.9
|
||||
|
||||
# Copy function code
|
||||
COPY app.py ${LAMBDA_TASK_ROOT}
|
||||
|
||||
# Install the function's dependencies using file requirements.txt
|
||||
# from your project folder.
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"
|
||||
|
||||
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
|
||||
CMD [ "app.handler" ]
|
138
tests/ci/metrics_lambda/app.py
Normal file
138
tests/ci/metrics_lambda/app.py
Normal file
@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import requests
|
||||
import argparse
|
||||
import jwt
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
from collections import namedtuple
|
||||
|
||||
def get_key_and_app_from_aws():
|
||||
import boto3
|
||||
secret_name = "clickhouse_github_secret_key_1"
|
||||
session = boto3.session.Session()
|
||||
client = session.client(
|
||||
service_name='secretsmanager',
|
||||
)
|
||||
get_secret_value_response = client.get_secret_value(
|
||||
SecretId=secret_name
|
||||
)
|
||||
data = json.loads(get_secret_value_response['SecretString'])
|
||||
return data['clickhouse-app-key'], int(data['clickhouse-app-id'])
|
||||
|
||||
def handler(event, context):
|
||||
private_key, app_id = get_key_and_app_from_aws()
|
||||
main(private_key, app_id, True)
|
||||
|
||||
def get_installation_id(jwt_token):
|
||||
headers = {
|
||||
"Authorization": f"Bearer {jwt_token}",
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
}
|
||||
response = requests.get("https://api.github.com/app/installations", headers=headers)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
return data[0]['id']
|
||||
|
||||
def get_access_token(jwt_token, installation_id):
|
||||
headers = {
|
||||
"Authorization": f"Bearer {jwt_token}",
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
}
|
||||
response = requests.post(f"https://api.github.com/app/installations/{installation_id}/access_tokens", headers=headers)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
return data['token']
|
||||
|
||||
|
||||
RunnerDescription = namedtuple('RunnerDescription', ['id', 'name', 'tags', 'offline', 'busy'])
|
||||
|
||||
def list_runners(access_token):
|
||||
headers = {
|
||||
"Authorization": f"token {access_token}",
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
}
|
||||
|
||||
response = requests.get("https://api.github.com/orgs/ClickHouse/actions/runners", headers=headers)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
print("Total runners", data['total_count'])
|
||||
runners = data['runners']
|
||||
result = []
|
||||
for runner in runners:
|
||||
tags = [tag['name'] for tag in runner['labels']]
|
||||
desc = RunnerDescription(id=runner['id'], name=runner['name'], tags=tags,
|
||||
offline=runner['status']=='offline', busy=runner['busy'])
|
||||
result.append(desc)
|
||||
return result
|
||||
|
||||
def push_metrics_to_cloudwatch(listed_runners, namespace):
|
||||
import boto3
|
||||
client = boto3.client('cloudwatch')
|
||||
metrics_data = []
|
||||
busy_runners = sum(1 for runner in listed_runners if runner.busy)
|
||||
metrics_data.append({
|
||||
'MetricName': 'BusyRunners',
|
||||
'Value': busy_runners,
|
||||
'Unit': 'Count',
|
||||
})
|
||||
total_active_runners = sum(1 for runner in listed_runners if not runner.offline)
|
||||
metrics_data.append({
|
||||
'MetricName': 'ActiveRunners',
|
||||
'Value': total_active_runners,
|
||||
'Unit': 'Count',
|
||||
})
|
||||
total_runners = len(listed_runners)
|
||||
metrics_data.append({
|
||||
'MetricName': 'TotalRunners',
|
||||
'Value': total_runners,
|
||||
'Unit': 'Count',
|
||||
})
|
||||
metrics_data.append({
|
||||
'MetricName': 'BusyRunnersRatio',
|
||||
'Value': busy_runners / total_active_runners * 100,
|
||||
'Unit': 'Percent',
|
||||
})
|
||||
|
||||
client.put_metric_data(Namespace='RunnersMetrics', MetricData=metrics_data)
|
||||
|
||||
def main(github_secret_key, github_app_id, push_to_cloudwatch):
|
||||
payload = {
|
||||
"iat": int(time.time()) - 60,
|
||||
"exp": int(time.time()) + (10 * 60),
|
||||
"iss": github_app_id,
|
||||
}
|
||||
|
||||
encoded_jwt = jwt.encode(payload, github_secret_key, algorithm="RS256")
|
||||
installation_id = get_installation_id(encoded_jwt)
|
||||
access_token = get_access_token(encoded_jwt, installation_id)
|
||||
runners = list_runners(access_token)
|
||||
if push_to_cloudwatch:
|
||||
push_metrics_to_cloudwatch(runners, 'RunnersMetrics')
|
||||
else:
|
||||
print(runners)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Get list of runners and their states')
|
||||
parser.add_argument('-p', '--private-key-path', help='Path to file with private key')
|
||||
parser.add_argument('-k', '--private-key', help='Private key')
|
||||
parser.add_argument('-a', '--app-id', type=int, help='GitHub application ID', required=True)
|
||||
parser.add_argument('--push-to-cloudwatch', action='store_true', help='Store received token in parameter store')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.private_key_path and not args.private_key:
|
||||
print("Either --private-key-path or --private-key must be specified", file=sys.stderr)
|
||||
|
||||
if args.private_key_path and args.private_key:
|
||||
print("Either --private-key-path or --private-key must be specified", file=sys.stderr)
|
||||
|
||||
if args.private_key:
|
||||
private_key = args.private_key
|
||||
else:
|
||||
with open(args.private_key_path, 'r') as key_file:
|
||||
private_key = key_file.read()
|
||||
|
||||
main(private_key, args.app_id, args.push_to_cloudwatch)
|
3
tests/ci/metrics_lambda/requirements.txt
Normal file
3
tests/ci/metrics_lambda/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
requests
|
||||
PyJWT
|
||||
cryptography
|
Loading…
Reference in New Issue
Block a user