【DevOps】推荐Go语言开源项目:Excelize ,获取阿里云ECS实例监控数据导出到自定义Excel表格(三)
目录
愿你前行的路上终有人陪😄~
安装要求
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使用率
目前效果
安装说明
设置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 "github.com/alibabacloud-go/cms-20190101/v2/client"
openapi "github.com/alibabacloud-go/darabonba-openapi/client"
"github.com/alibabacloud-go/tea/tea"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/cms"
"github.com/xuri/excelize/v2"
_ "github.com/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格式数据
默认得到的数据格式是带请求头的,并且有很多数据不需要
得到的Monitor_Data
值嵌套多个结构体,把需要的数据拿出来,也就是:Monitor_Data_Body_Datapoints := *Monitor_Data.Body.Datapoints
注意格式:
[{},{}]
这样的格式可以序列化成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列指定位置
相关文章
- [转]Java中导入、导出Excel
- CSDN学霸课表——Excel超赞新功能上线:多人实时编辑
- Python 界面教程之8个excel csv数据分析程序通过PySimpleGUI封装成exe和macos桌面程序
- Excel 数据透视表教程大全之 02 添加字段、设置数据格式应用货币模式、按值进行排序(教程含样本数据)
- EXCEL-对筛选出(单独手动隐藏行还是在统计范围内)的表格数据进行统计
- Java实现将Excel导入数据库和从数据库中导出为Excel
- 小学生python游戏编程arcade----excel调用
- 在Excel VBA中,单元格的.interior.color的值是什么格式的?
- Excel带条件求和——SUMIF函数
- 【C#】读取Excel中嵌套的Json对象,Json带斜杠的问题(其一)
- 20180804 excel规划求解。。。
- [Excel知识技能] 将数值格式数字转换为文本格式
- Excel知识技能汇总
- [Excel函数] COUNT函数 | COUNTIF函数 | COUNTIFS函数