使用OpenAPI批量获取阿里云实例监控数据

发布于 2020-04-09  19.81k 次阅读


想要观察阿里云上所有实例每周的cpu 平均使用率情况,根据阿里OpenAPI 提供的 " DescribeInstanceMonitorData " api来获取实例所有监控数据,之后再处理数据得到自己想要的指标。

OpenAPI 网址: https://api.aliyun.com

  • 使用 python3
  • 需要安装阿里OpenAPI SDK: python3 -m pip install aliyun-python-sdk-ecs

官方提供的 DescribeInstanceMonitorData python 版代码:


#!/usr/bin/env python
#coding=utf-8

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkecs.request.v20140526.DescribeInstanceMonitorDataRequest import DescribeInstanceMonitorDataRequest

client = AcsClient('<accessKeyId>', '<accessSecret>', 'cn-hangzhou')

request = DescribeInstanceMonitorDataRequest()
request.set_accept_format('json')

request.set_InstanceId("InstanceId")
request.set_StartTime("2020-04-09T00:00:00Z")
request.set_EndTime("2020-04-09T12:00:00Z")
request.set_Period(600)

response = client.do_action_with_exception(request)
# python2:  print(response) 
print(str(response, encoding='utf-8'))

修改成适合自己使用的:


#!/usr/bin/env python
# coding=utf-8
import json
import csv
from datetime import datetime, date
from datetime import timedelta
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkecs.request.v20140526.DescribeInstanceMonitorDataRequest import DescribeInstanceMonitorDataRequest
from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest


def get_ecs_instance(access_key_id, access_secret):
    client = AcsClient(access_key_id, access_secret, 'cn-hangzhou')  # us-east-1
    request = DescribeInstancesRequest()
    request.set_accept_format('json')
    request.set_PageNumber(1)
    request.set_PageSize(100)
    ins_ids = []
    response = client.do_action_with_exception(request)
    js = json.loads(response)
    for i in js["Instances"]['Instance']:
        ins_id = i["InstanceId"]
        ins_ids.append(ins_id)
    total_count = js["TotalCount"]
    if int(total_count) > 100:
        request.set_PageNumber(2)
        response = client.do_action_with_exception(request)
        js = json.loads(response)
        for i in js["Instances"]['Instance']:
            ins_id = i["InstanceId"]
            ins_ids.append(ins_id)
    return ins_ids


def get_ecs_info(access_key_id, access_secret, instance_id):
    client = AcsClient(access_key_id, access_secret, 'cn-hangzhou')
    request = DescribeInstancesRequest()
    request.set_accept_format('json')

    request.set_InstanceIds(f"[\"{instance_id}\"]")

    response = client.do_action_with_exception(request)
    js = json.loads(response)
    ins = js["Instances"]['Instance'][0]
    # create_time = ins["CreationTime"]
    # expire_time = ins["ExpiredTime"]
    instance_name = ins["InstanceName"]
    # os_name = ins["OSName"]
    # status = ins["Status"]
    intranet_ip = ins["VpcAttributes"]["PrivateIpAddress"]["IpAddress"][0]
    if ins["EipAddress"]["IpAddress"]:
        eip = ins["EipAddress"]["IpAddress"]
        # bandwidth = ins["EipAddress"]["Bandwidth"]
    else:
        eip = '-'
        # bandwidth = ins["InternetMaxBandwidthOut"]
    public_ip = ins["PublicIpAddress"]["IpAddress"][0] if ins["PublicIpAddress"]["IpAddress"] else eip
    # cpu = ins["Cpu"]
    # memory = ins["Memory"]
    # ins_type = ins["InstanceType"]
    try:
        group = ins["Tags"]["Tag"][0]["TagValue"]
    except:
        group = '-'
    return instance_name, intranet_ip, public_ip, group


# 获取 n 天前时间,并格式化为api指定格式时间戳
def get_date(days=0):
    return (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%dT%H:%M:00Z")


# 格式化json输出
def get_pretty_print(res):
    dat = json.loads(res)
    js = json.dumps(dat, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
    return js


# 设置获取起始时间点(阿里api限制,故每次获取一天数据)并获取数据
def do_request(access_key_id, access_secret, days=0, ins_id=""):
    client = AcsClient(access_key_id, access_secret, 'cn-hangzhou')
    instance_id = []  # 在此填入所有阿里实例ID,如:instance_id = ["i-bp1db2tn3cvfxxxxxxxx", "i-bp1auiw4jkbbxxxxxxxx"]  所有实例ID可由另一个api "DescribeInstances" 获得
    request = DescribeInstanceMonitorDataRequest()
    request.set_accept_format('json')
    start_time = get_date(days)  # 起始时间
    end_time = get_date(days - 1)  # 截止时间
    request.set_InstanceId(ins_id)
    request.set_StartTime(start_time)
    request.set_EndTime(end_time)
    request.set_Period(600)  # 获取监控数据的间隔时间,设置为10分钟,阿里每次最多返回400条监控数据
    res = client.do_action_with_exception(request)
    return res


# key.txt 包含形如 '英合  LTAI4FzbQHxxxxxxxxxxx   h9jINL03zxxxxxxxxxxxxxxxx' 的key
with open('key.txt', 'r', encoding='utf-8') as f:
    data = f.readlines()
with open('ali_cpu.csv', 'w', encoding='utf-8', newline="") as f:
    writer = csv.writer(f)
    writer.writerow(
        ['实例ID', '名称', '公网ip', '内网ip', '7天平均CPU', '项目', '账号'])
    for string in data:
        account_name, access_key_id, access_secret = [n for n in string.split()]
        ins_ids = get_ecs_instance(access_key_id, access_secret)
        print(ins_ids)

        for ins in ins_ids:
            avg_s = 0
            try:
                for day in range(7, 0, -1):  # 获取一周数据
                    r = do_request(access_key_id, access_secret, day, ins)
                    js = json.loads(r)
                    datas = js["MonitorData"]["InstanceMonitorData"]
                    sum = 0
                    for d in datas:
                        cpu = d['CPU'] if 'CPU' in d.keys() else 0
                        sum += cpu
                    avg = sum / len(datas)
                    avg_s += avg
            except Exception as e:
                print(e, ins)
            avg_7d = int(avg_s / 7)
            instance_name, intranet_ip, public_ip, group = get_ecs_info(access_key_id, access_secret, ins)
            row = [ins, instance_name, public_ip, intranet_ip, avg_7d, group, account_name]
            writer.writerow(row)
            print(f'{instance_name} done')

需要观察其他指标可自行处理监控数据项。