推荐Go语言开源项目:Excelize ,获取阿里云ECS实例监控数据导出到自定义Excel表格(二)

简介: 推荐Go语言开源项目:Excelize ,获取阿里云ECS实例监控数据导出到自定义Excel表格(二)

需求


用阿里云云监控服务:

阿里云云监控没有grafana服务端,生成不了PDF,再加上Prometheus不能生成exl表格数据,阿里云云监控企业版太贵,一个报表0.14元。我们可以自己调取阿里云的api接口,获取ECS主机cpu负载、内存使用率等信息,生成报表定时发送指定邮箱。


有人会说了,为啥不自己搭建一个Prometheus服务端,然后把所有主机全部添加到自己的服务器上。这个想法好,但是如果“二次开发”阿里云 云监控平台,我们公司就不用单独购买服务器,毕竟人家做的也不错,除了有些功能收费以外。其实自己搭建Prometheus服务端我们已经实现了,目前可以做到监控数据生成PDF格式定时发送,动态添加主机(自动增删被监控主机,还未整理,主要是懒🌚),只不过想节省资源,也能为公司每个月省下好几百。


目前进度


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

2、(进行中) 已获取所有主机主机名和ip信息

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

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


效果一:获取单台主机资源信息


获取一个主机的7天内的cpu使用率信息,生成报表

1675242552355.jpg


阿里云API


阿里云 云监控服务API地址:https://next.api.aliyun.com/home

本篇使用的API网址:https://next.api.aliyun.com/api/Cms/2019-01-01/DescribeMetricTop?params={}


代码示例


// This file is auto-generated, don't edit it. Thanks.
package main
import (
  "encoding/json"
  "fmt"
  "github.com/xuri/excelize/v2"
  "os"
  cms20190101  "github.com/alibabacloud-go/cms-20190101/v2/client"
  openapi  "github.com/alibabacloud-go/darabonba-openapi/client"
  "github.com/alibabacloud-go/tea/tea"
  "strings"
)
type List 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"`
}
/**
 * 使用AK&SK初始化账号Client
 * @param accessKeyId
 * @param accessKeySecret
 * @return Client
 * @throws Exception
 */
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) {
  client, _err := CreateClient(tea.String("LTxxxxxxxxx5dUc"), tea.String("G1WxxxxxxxxxxxxxxxxxxiF6"))
  if _err != nil {
    return _err
  }
  describeMetricListRequest := &cms20190101.DescribeMetricListRequest{
    StartTime: tea.String("1636905600000"),
    EndTime: tea.String("1637424000000"),
    MetricName: tea.String("cpu_total"),
    Namespace: tea.String("acs_ecs_dashboard"),
    Dimensions: tea.String("{\"instanceId\":\"i-8vxxxxxxxxgh\"}"),
    Period: tea.String("604800"),
  }
  // 复制代码运行请自行打印 API 的返回值
  M, _err := client.DescribeMetricList(describeMetricListRequest)
  N := *M.Body.Datapoints
  fmt.Println(N)
  N1 := strings.TrimLeft(N, "[")
  N2 := strings.TrimRight(N1, "]")
  //fmt.Printf("N类型:%T,N值:%v\n",N2,N2)
  fmt.Println(N2)
  var list List
  err1 := json.Unmarshal([]byte(N2), &list)
  if err1 != nil {
    fmt.Printf("序列化转化失败,%v",err1)
  }else {
    fmt.Println("序列化转化成功")
  }
  fmt.Println(list)
  f := excelize.NewFile()
  // 创建一个工作表
  index := f.NewSheet("主机列表")
  err2 := f.SetColWidth("主机列表", "A", "H", 23)
  if err2 != nil {
    fmt.Printf("表格创建失败,%v",err2)
  }else {
    fmt.Println("表格创建成功")
  }
  // 设置单元格的值
  f.SetCellValue("主机列表", "A1", "实例ID号")
  f.SetCellValue("主机列表", "A2", list.InstanceId)
  f.SetCellValue("主机列表","B1","7天CPU最小使用率")
  f.SetCellValue("主机列表","B2",list.Minimum)
  f.SetCellValue("主机列表","C1","7天CPU最大使用率")
  f.SetCellValue("主机列表","C2",list.Maximum)
  f.SetCellValue("主机列表","D1","7天CPU平均使用率")
  f.SetCellValue("主机列表","D2",list.Average)
  // 设置工作簿的默认工作表
  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)
  }
}


效果二:获取所有主机资源信息


1675242589646.jpg


阿里云API


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

https://next.api.aliyun.com/api/Cms/2019-01-01/DescribeMetricLast?params={}


说实话,不知道这两个有什么区别。都可以用,而且两个获得数据不准,乱七八糟!先讲究用吧


代码实例


获取所有主机监控数据

// 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/xuri/excelize/v2"
  _ "github.com/xuri/excelize/v2"
  "os"
  "strconv"
)
type List 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"`
}
/**
 * 使用AK&SK初始化账号Client
 * @param accessKeyId
 * @param accessKeySecret
 * @return Client
 * @throws Exception
 */
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) {
  client, _err := CreateClient(tea.String("LTAIxxxxxxxxxxx"), tea.String("G1WBNxxxxxxxxxxxxxxxxxxxxxx"))
  if _err != nil {
    return _err
  }
  describeMetricListRequest := &cms20190101.DescribeMetricListRequest{
    StartTime:  tea.String("1636905600000"),
    EndTime:    tea.String("1637424000000"),
    MetricName: tea.String("cpu_total"),
    Namespace:  tea.String("acs_ecs_dashboard"),
    Dimensions: tea.String(""),
    Period:     tea.String("604800"),
  }
  // 复制代码运行请自行打印 API 的返回值
  M, _err := client.DescribeMetricList(describeMetricListRequest)
  N := *M.Body.Datapoints
  //fmt.Println("N值\n", N)
  var slice []map[string]interface{}
  //注意:反序列化map,不需要make,因为make操作被封装到Unmarshal函数
  err := json.Unmarshal([]byte(N), &slice)
  if err != nil {
    fmt.Printf("unmarshal err=%v\n", err)
  }
  f := excelize.NewFile()
  index := f.NewSheet("主机列表")
  f.SetCellValue("主机列表", "A1", "实例ID号")
  f.SetCellValue("主机列表", "B1", "7天内的CPU最大使用率")
  f.SetCellValue("主机列表", "C1", "7天内的CPU最小使用率")
  f.SetCellValue("主机列表", "D1", "7天内的CPU平均使用率")
  f.SetColWidth("主机列表", "A", "H", 23)
/*  fmt.Printf("反序列化后:%v\n", slice)
  fmt.Println("第一个切片是:", slice[0])
  fmt.Println("第二个切片是:", slice[1])
  //获取第一个主机信息
  Arr, err := json.Marshal(slice[0])
  if err != nil {
    fmt.Println(err)
    return
  }
  var List1 List
  err = json.Unmarshal(Arr, &List1)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(List1)
  f.SetCellValue("主机列表", "A2", List1.InstanceId)
  f.SetCellValue("主机列表", "B2", List1.Maximum)
  f.SetCellValue("主机列表", "C2", List1.Minimum)
  f.SetCellValue("主机列表", "D2", List1.Average)
    //获取第二个主机信息
  Arr1, err := json.Marshal(slice[1])
  if err != nil {
    fmt.Println(err)
    return
  }
  var List2 List
  err = json.Unmarshal(Arr1, &List2)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(List2)
  f.SetCellValue("主机列表", "A3", List2.InstanceId)
  f.SetCellValue("主机列表", "B3", List2.Maximum)
  f.SetCellValue("主机列表", "C3", List2.Minimum)
  f.SetCellValue("主机列表", "D3", List2.Average)
*/
//把上面单个获取主机方式改成for循环
  for  i :=2 ;i < len(slice); i++ {
    A1 :="A"
    //strconv.Itoa函数 可以将int类型转string类型
    A2 := fmt.Sprint(A1 + strconv.Itoa(i))
    B1 :="B"
    B2 := fmt.Sprint(B1 + strconv.Itoa(i))
    C1 :="C"
    C2 := fmt.Sprint(C1 + strconv.Itoa(i))
    D1 :="D"
    D2 := fmt.Sprint(D1 + strconv.Itoa(i))
    Arr, err := json.Marshal(slice[i-2])
    if err != nil {
      fmt.Println(err)
      return
    }
    var List1 List
    err = json.Unmarshal(Arr, &List1)
    if err != nil {
      fmt.Println(err)
      return
    }
    //fmt.Println(List1)
    f.SetCellValue("主机列表", A2, List1.InstanceId)
    f.SetCellValue("主机列表", B2, List1.Maximum)
    f.SetCellValue("主机列表", C2, List1.Minimum)
    f.SetCellValue("主机列表", D2, List1.Average)
  }
  // 设置工作簿的默认工作表
  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)
  }
}
相关实践学习
通义万相文本绘图与人像美化
本解决方案展示了如何利用自研的通义万相AIGC技术在Web服务中实现先进的图像生成。
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情:&nbsp;https://www.aliyun.com/product/ecs
相关文章
|
8月前
|
移动开发 JavaScript 前端开发
精通服务器推送事件(SSE)与 Python 和 Go 实现实时数据流 🚀
服务器推送事件(SSE)是HTML5规范的一部分,允许服务器通过HTTP向客户端实时推送更新。相比WebSocket,SSE更轻量、简单,适合单向通信场景,如实时股票更新或聊天消息。它基于HTTP协议,使用`EventSource` API实现客户端监听,支持自动重连和事件追踪。虽然存在单向通信与连接数限制,但其高效性使其成为许多轻量级实时应用的理想选择。文中提供了Python和Go语言的服务器实现示例,以及HTML/JavaScript的客户端代码,帮助开发者快速集成SSE功能,提升用户体验。
|
4月前
|
人工智能 负载均衡 监控
使用 Go 和 Gin 实现高可用负载均衡代理服务器
本文基于Go语言和Gin框架,实现了一个企业级负载均衡代理服务器,支持动态路由、健康检查、会话保持等功能。具备高可用性与高性能,单节点支持100k+ QPS,延迟达亚毫秒级,并提供完整的压力测试方案与优化建议。
157 7
|
4月前
|
JSON 前端开发 Go
Go语言实战:创建一个简单的 HTTP 服务器
本篇是《Go语言101实战》系列之一,讲解如何使用Go构建基础HTTP服务器。涵盖Go语言并发优势、HTTP服务搭建、路由处理、日志记录及测试方法,助你掌握高性能Web服务开发核心技能。
|
4月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
384 0
|
7月前
|
人工智能 搜索推荐 程序员
用 Go 语言轻松构建 MCP 客户端与服务器
本文介绍了如何使用 mcp-go 构建一个完整的 MCP 应用,包括服务端和客户端两部分。 - 服务端支持注册工具(Tool)、资源(Resource)和提示词(Prompt),并可通过 stdio 或 sse 模式对外提供服务; - 客户端通过 stdio 连接服务器,支持初始化、列出服务内容、调用远程工具等操作。
1801 4
|
7月前
|
Go API 定位技术
MCP 实战:用 Go 语言开发一个查询 IP 信息的 MCP 服务器
随着 MCP 的快速普及和广泛应用,MCP 服务器也层出不穷。大多数开发者使用的 MCP 服务器开发库是官方提供的 typescript-sdk,而作为 Go 开发者,我们也可以借助优秀的第三方库去开发 MCP 服务器,例如 ThinkInAIXYZ/go-mcp。 本文将详细介绍如何在 Go 语言中使用 go-mcp 库来开发一个查询 IP 信息的 MCP 服务器。
454 0
|
9月前
|
文字识别 Serverless 开发工具
【全自动改PDF名】批量OCR识别提取PDF自定义指定区域内容保存到 Excel 以及根据PDF文件内容的标题来批量重命名
学校和教育机构常需处理成绩单、报名表等PDF文件。通过OCR技术,可自动提取学生信息并录入Excel,便于统计分析和存档管理。本文介绍使用阿里云服务实现批量OCR识别、内容提取、重命名及导出表格的完整步骤,包括开通相关服务、编写代码、部署函数计算和设置自动化触发器等。提供Python示例代码和详细操作指南,帮助用户高效处理PDF文件。 链接: - 百度网盘:[链接](https://pan.baidu.com/s/1mWsg7mDZq2pZ8xdKzdn5Hg?pwd=8866) - 腾讯网盘:[链接](https://share.weiyun.com/a77jklXK)
1161 5
|
关系型数据库 MySQL Shell
不通过navicat工具怎么把查询数据导出到excel表中
不通过navicat工具怎么把查询数据导出到excel表中
163 0
|
easyexcel Java UED
SpringBoot中大量数据导出方案:使用EasyExcel并行导出多个excel文件并压缩zip后下载
在SpringBoot环境中,为了优化大量数据的Excel导出体验,可采用异步方式处理。具体做法是将数据拆分后利用`CompletableFuture`与`ThreadPoolTaskExecutor`并行导出,并使用EasyExcel生成多个Excel文件,最终将其压缩成ZIP文件供下载。此方案提升了导出效率,改善了用户体验。代码示例展示了如何实现这一过程,包括多线程处理、模板导出及资源清理等关键步骤。
|
前端开发 JavaScript
使用Vue+xlsx+xlsx-style实现导出自定义样式的Excel文件
本文介绍了在Vue项目中使用`xlsx`和`xlsx-style`(或`xlsx-style-vite`)库实现导出具有自定义样式的Excel文件的方法,并提供了详细的示例代码和操作效果截图。
2376 2
使用Vue+xlsx+xlsx-style实现导出自定义样式的Excel文件

热门文章

最新文章

下一篇
oss云网关配置