愿你前行的路上终有人陪????~

安装要求

1、Golang版本 1.15+

2、调用阿里云API权限

目标

利用阿里云现有的云监控服务,生成自定义数据报表。

以七天为周期定时收集数据发送到企业邮箱

目前调用了两种阿里云API

获取监控数据API:查询指定云服务时序指标的监控数据

​https://next.api.aliyun.com/api/Cms/2019-01-01/DescribeMetricList?params={}&sdkStyle=old​​​

获取主机信息API:查询所有已安装和未安装云监控插件的主机列表

​https://next.api.aliyun.com/api/Cms/2019-01-01/DescribeMonitoringAgentHosts?params={}&sdkStyle=old&tab=DEBUG​​​

目前进度

1、(完成) 已获取所有主机指定时间段内的各种指标(目前该项目以cpu使用率为例)

2、(完成) 已获取所有主机主机名和ip信息

3、(完成) 把接口一获取到的instanceid和接口二获得的instanceid对比,如果相等,把接口二获取的主机名和ip写到该表行的“主机名”与“IP”列

4、(进行中)获取整个周期时间段数据的百分比,例如7天内,在10-12点的cpu使用率

目前效果

推荐Go语言开源项目:Excelize ,获取阿里云监控数据,导入自定义Excel表格(三)_阿里云

安装说明

设置GOPROXY,创建mod环境

GOPROXY=https://goproxy.cn
go mod tidy

main.go

// This file is auto-generated, don't edit it. Thanks.
package main

import (
"encoding/json"
"fmt"
cms20190101 "/alibabacloud-go/cms-20190101/v2/client"
openapi "/alibabacloud-go/darabonba-openapi/client"
"/alibabacloud-go/tea/tea"
"/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"/aliyun/alibaba-cloud-sdk-go/services/cms"
"/xuri/excelize/v2"
_ "/xuri/excelize/v2"
"os"
"strconv"
)

type Monitor_data_struct struct {
Order int `json:"order"`
Timestamp int `json:"timestamp"`
UserId string `json:"userId"`
InstanceId string `json:"instanceId"`
Minimum float32 `json:"Minimum"`
Maximum float32 `json:"Maximum"`
Average float32 `json:"Average"`
Count float32 `json:"_count"`
}


func CreateClient(accessKeyId *string, accessKeySecret *string) (_result *cms20190101.Client, _err error) {
config := &openapi.Config{
// 您的AccessKey ID
AccessKeyId: accessKeyId,
// 您的AccessKey Secret
AccessKeySecret: accessKeySecret,
}
// 访问的域名
config.Endpoint = tea.String("metrics.cn-hangzhou.aliyuncs.com")
_result = &cms20190101.Client{}
_result, _err = cms20190101.NewClient(config)
return _result, _err
}

func _main(args []*string) (_err error) {
//******调用接口******

//调用接口一:获取监控数据
metrics_client, _err := CreateClient(tea.String("LTxxxxxxxxxxxxxp3G"), tea.String("0Tn7xxxxxxxxxxxxxxxxxxRGr6GAr"))
if _err != nil {
return _err
}

describeMetricListRequest := &cms20190101.DescribeMetricListRequest{
StartTime: tea.String("1637769600000"), //开始时间
EndTime: tea.String("1637856000000"), //结束时间
MetricName: tea.String("cpu_total"), //cpu使用率
Namespace: tea.String("acs_ecs_dashboard"), //ecs实例
Dimensions: tea.String(""), //全部实例
Period: tea.String("604800"), //周期7天 ,60x60x24x7
}

//******获取数据******
// 获取接口一API数据,输出到Monitor_Data
Monitor_Data, _err := metrics_client.DescribeMetricList(describeMetricListRequest)
//输出M的Body。Datapoints段数据到N
Monitor_Data_Body_Datapoints := *Monitor_Data.Body.Datapoints
//******序列化******
//开始序列化接口一,这里可以直接进行反序列化,因为得到的数据格式与序列化后的格式一致
//创建map类型,把Monitor_Data_Body_Datapoints反序列化成map类型
var Monitor_data_struct_json_InstanceId_map = make(map[string]string, 200)
var Ecs_Data_HostnameIp_struct_map_hostname = make(map[string]string, 200)
var Ecs_Data_HostnameIp_struct_map_ip =make(map[string]string,200)
//注意:反序列化map,不需要make,因为make操作被封装到Unmarshal函数
var Monitor_Data_Body_Datapoints_map []map[string]interface{}
err := json.Unmarshal([]byte(Monitor_Data_Body_Datapoints), &Monitor_Data_Body_Datapoints_map)
if err != nil {
fmt.Printf("unmarshal err=%v\n", err)
}

//创建文件,规定表头
var f = excelize.NewFile()
var Index = f.NewSheet("主机列表")
f.SetCellValue("主机列表", "A1", "实例ID号")
f.SetCellValue("主机列表", "B1", "主机名")
f.SetCellValue("主机列表", "C1", "IP")
f.SetCellValue("主机列表", "D1", "CPU最小使用率/周")
f.SetCellValue("主机列表", "E1", "CPU最大使用率/周")
f.SetCellValue("主机列表", "F1", "CPU平均使用率/周")
f.SetColWidth("主机列表", "A", "C", 27)
f.SetColWidth("主机列表", "D", "F", 18)
//循环取map中得值,序列化结构体后取值写入到exl表格中
for i := 0; i < len(Monitor_Data_Body_Datapoints_map); i++ {
Alist := "A"
Aline := fmt.Sprint(Alist + strconv.Itoa(i+2))
Dlist := "D"
Dline := fmt.Sprint(Dlist + strconv.Itoa(i+2))
Elist := "E"
Eline := fmt.Sprint(Elist + strconv.Itoa(i+2))
Flist := "F"
Fline := fmt.Sprint(Flist + strconv.Itoa(i+2))
Arr, err := json.Marshal(Monitor_Data_Body_Datapoints_map[i])
if err != nil {
fmt.Println(err)
return
}
var Monitor_data_struct_json Monitor_data_struct
err = json.Unmarshal(Arr, &Monitor_data_struct_json)
if err != nil {
fmt.Println(err)
return
}
//每一个实例ID都不一样
Monitor_data_struct_json_InstanceId_map[Monitor_data_struct_json.InstanceId] = Monitor_data_struct_json.InstanceId

f.SetCellValue("主机列表", Aline, Monitor_data_struct_json.InstanceId)
f.SetCellValue("主机列表", Dline, Monitor_data_struct_json.Minimum)
f.SetCellValue("主机列表", Eline, Monitor_data_struct_json.Maximum)
f.SetCellValue("主机列表", Fline, Monitor_data_struct_json.Average)
}

// ================================================================================================
//开始调用第二个接口,定义一些变量
type Ecs_Data_Hosts_Host_json_map []map[string]interface{}
type Ecs_Data_Hosts_Host struct {
Host Ecs_Data_Hosts_Host_json_map
}
type Ecs_Data_HostnameIp_struct struct {
HostName string `json:"HostName"`
InstanceId string `json:"InstanceId"`
IpGroup string `json:"IpGroup"`
}
type Ecs_Data_struct struct {
Code string `json:"Code"`
Message string `json:"Message"`
Success bool `json:"Success"`
RequestId string `json:"RequestId"`
PageTotal int `json:"PageTotal"`
Total int `json:"Total"`
PageSize int `json:"PageSize"`
PageNumber int `json:"PageNumber"`
Hosts Ecs_Data_Hosts_Host `json:"Hosts"`
}

//调用接口二:获取主机名和IP(上一个接口没有主机名和IP,所以需要拼接下)
ecs_client, err := cms.NewClientWithAccessKey("cn-zhangjiakou", "LTxxxxxxxxxxxxxxxxxx3G", "0TxxxxxxxxxxxxxxxxxxxAr")
request := cms.CreateDescribeMonitoringAgentHostsRequest()
request.Scheme = "https"

request.AliyunHost = requests.NewBoolean(true) //阿里云云监控服务可以自己添加其他类型主机,这里等于true代表只处理阿里云ecs主机,等于false处理不是阿里云ecs的主机
//获取接口二API数据,输出到Ecs_Data
Ecs_Data, err := ecs_client.DescribeMonitoringAgentHosts(request)
if err != nil {
fmt.Print(err.Error())
}

//开始序列化
Ecs_Data_json, err := json.Marshal(Ecs_Data)
if err != nil {
fmt.Println(err)
}
var Ecs_Data_struct_json Ecs_Data_struct
err = json.Unmarshal([]byte(Ecs_Data_json), &Ecs_Data_struct_json)
if err != nil {
fmt.Println(err)
}
//循环
for i:=0; i < len(Ecs_Data_struct_json.Hosts.Host);i++ {
Ecs_Data_Hosts_Host_map, err := json.Marshal(Ecs_Data_struct_json.Hosts.Host[i])
if err != nil {
fmt.Println(err)
}
//fmt.Println("结构体序列化",string(Ecs_Data_Hosts_Host_map))
var Ecs_Data_HostnameIp_struct Ecs_Data_HostnameIp_struct
err = json.Unmarshal([]byte(Ecs_Data_Hosts_Host_map), &Ecs_Data_HostnameIp_struct)
Ecs_Data_HostnameIp_struct_map_hostname[Ecs_Data_HostnameIp_struct.InstanceId] = Ecs_Data_HostnameIp_struct.HostName
Ecs_Data_HostnameIp_struct_map_ip[Ecs_Data_HostnameIp_struct.InstanceId] = Ecs_Data_HostnameIp_struct.IpGroup
}


//==================================================================================================================
// 设置工作簿的默认工作表
f.SetActiveSheet(Index)
// 根据指定路径保存文件
if err := f.SaveAs("Book1.xlsx"); err != nil {
fmt.Println(err)
}

for k, v := range Ecs_Data_HostnameIp_struct_map_hostname {
Monitor_data_struct_json_InstanceId_map[k] = v
}

f, err = excelize.OpenFile("Book1.xlsx")
if err != nil {
fmt.Println(err)
return
}
for i := 2; i < len(Monitor_Data_Body_Datapoints_map); i++ {
Alist := "A"
Aline := fmt.Sprint(Alist + strconv.Itoa(i))
Blist := "B"
Bline := fmt.Sprint(Blist + strconv.Itoa(i))
//获取Book1,xlsx表格指定位置的值
cell, err := f.GetCellValue("主机列表", Aline)
if err != nil {
fmt.Println(err)
return
}

//fmt.Println(cell,Ecs_Data_HostnameIp_struct_map_hostname[cell])
f.SetCellValue("主机列表", Bline,Monitor_data_struct_json_InstanceId_map[cell])
}
// 设置工作簿的默认工作表
f.SetActiveSheet(Index)
// 根据指定路径保存文件
if err := f.SaveAs("Book1.xlsx"); err != nil {
fmt.Println(err)
}
for k, v := range Ecs_Data_HostnameIp_struct_map_ip {
Monitor_data_struct_json_InstanceId_map[k] = v
}
f, err = excelize.OpenFile("Book1.xlsx")
if err != nil {
fmt.Println(err)
return
}
for i := 2; i < len(Monitor_Data_Body_Datapoints_map); i++ {
Alist := "A"
Aline := fmt.Sprint(Alist + strconv.Itoa(i))
C1 := "C"
C2 := fmt.Sprint(C1 + strconv.Itoa(i))
//获取Book1,xlsx表格指定位置的值
cell, err := f.GetCellValue("主机列表", Aline)
if err != nil {
fmt.Println(err)
return
}

//fmt.Println(cell,Ecs_Data_HostnameIp_struct_map_ip[cell])
f.SetCellValue("主机列表", C2,Monitor_data_struct_json_InstanceId_map[cell])
}

//开启表保护,密码:123456
f.ProtectSheet("主机列表", &excelize.FormatSheetProtection{
Password: "123456",
EditScenarios: false,
})
// 设置工作簿的默认工作表
f.SetActiveSheet(Index)
// 根据指定路径保存文件
if err := f.SaveAs("Book1.xlsx"); err != nil {
fmt.Println(err)
}

if _err != nil {
return _err
}
return _err
}



func main() {
err := _main(tea.StringSlice(os.Args[1:]))
if err != nil {
panic(err)
}
}

调用思路

1、调用阿里云API接口一获得实例ID、CPU使用信息 JSON格式数据

默认得到的数据格式是带请求头的,并且有很多数据不需要

推荐Go语言开源项目:Excelize ,获取阿里云监控数据,导入自定义Excel表格(三)_golang_02

得到的​​Monitor_Data​​值嵌套多个结构体,把需要的数据拿出来,也就是:​​Monitor_Data_Body_Datapoints := *Monitor_Data.Body.Datapoints​

推荐Go语言开源项目:Excelize ,获取阿里云监控数据,导入自定义Excel表格(三)_golang_03

注意格式:

[{},{}]

这样的格式可以序列化成map类型的切片​​[]map[string]interface{}​​,序列化后得到的值格式​​[map[] map[] map[]...]​​,这样的数据其实还是一个切片,我们直接获取元素位置即可得到里面的数据,然后序列化成json格式,最后通过for循环每一个切片的map类型值序列化成结构体,取到其中的值写入到exl表格中。

具体其中一个循环是这样的:

1、得到第0个元素的值

[ map[ ] ]  ---> Monitor_Data_Body_Datapoints_map[0]

2、把第0个元素得到的值,序列化成json

Arr, err := json.Marshal(Monitor_Data_Body_Datapoints_map[0])

得到格式:

{"Average":0.7308333333333331,"Maximum":50.76,"Minimum":0,"instanceId":"i-8vb1h2roxxxxxxxxxx","timestamp":1637798400000,"userId":"1541654291217958"}

3、反序列化成结构体

var Monitor_data_struct_json Monitor_data_struct
json.Unmarshal(Arr, &Monitor_data_struct_json)

得到格式:

main.Monitor_data_struct{Order:0, Timestamp:1637798400000, UserId:"1541654291217958", InstanceId:"i-8vbdzk5bxz93j4qx4jou", Minimum:0.52, Maximum:88.14, Average:5.8727
083, Count:0}

4、添加数据到​​Monitor_data_struct_json_InstanceId_map​

每一个实例ID都不一样,for循环后,将得到所有实例ID和cpu使用信息,依次写入到​​Monitor_data_struct_json_InstanceId_map​​,下面用于遍历第二个接口赋值

5、最后就可以直接获取值写入到exl表格了

f.SetCellValue("主机列表", Aline, Monitor_data_struct_json.InstanceId)

2、调用阿里云API接口二获取实例ID、主机名、IP JSON格式数据

主要就干了一件事:

Ecs_Data_HostnameIp_struct_map_hostname[Ecs_Data_HostnameIp_struct.InstanceId] = Ecs_Data_HostnameIp_struct.HostName
Ecs_Data_HostnameIp_struct_map_ip[Ecs_Data_HostnameIp_struct.InstanceId] = Ecs_Data_HostnameIp_struct.IpGroup

for循环得到所有map数据,写入到​​Ecs_Data_HostnameIp_struct_map_hostname​​,​​Ecs_Data_HostnameIp_struct_map_ip​

这样就得到了所有主机的hostnmae和IP,都带有实例ID,下面会通过实例ID为媒介,把hostname和IP与实例ID一一对应,写入到exl表格中

3、遍历主机名的map和IP的map,通过共有实例ID一一对应,写入到exl表格

1、通过for循环,得到Book1.xlsx表格指定位置的值,这里是获取了每一个A列的值,就赋值到C列指定位置