React使用Recharts繪製AWS EC2 Instance CPUUtilization指標折線圖(line chart)。
事前要求
參考「React 安裝Recharts圖表函式庫」建立Raect專案。
參考「Golang 取得AWS CloudWatch metric統計資料」透過Go取得AWS指標統計資料。
Go
建立Go後端Gin web專案,提供GET| [DOMAIN]/cpu-utilization
REST API給前端呼叫來取得AWS EC2 instance的CPUUtilization指標資料。
package main
import (
"context"
"net/http"
"sort"
"strconv"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch/types"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/samber/lo"
)
func main() {
router := gin.Default() // get gin engine
router.Use(cors.Default()) // allow cors
router.GET("/cpu-utilization", HandleCpuUtilization)
router.Run()
}
func NewCloudWatchClient(ctx context.Context) *cloudwatch.Client {
cfg, err := config.LoadDefaultConfig(
ctx,
config.WithRegion("ap-northeast-1"),
)
if err != nil {
panic(err)
}
return cloudwatch.NewFromConfig(cfg)
}
type QueryString struct {
StartTime *time.Time `form:"startTime" binding:"required" time_format:"2006-01-02T15:04:05" time_utc:"1"`
EndTime *time.Time `form:"endTime" binding:"required" time_format:"2006-01-02T15:04:05" time_utc:"1"`
}
func HandleCpuUtilization(c *gin.Context) {
ctx := c.Request.Context()
var q QueryString
err := c.BindQuery(&q)
if err != nil {
c.Error(err)
return
}
client := NewCloudWatchClient(ctx)
output, err := client.GetMetricStatistics(ctx, &cloudwatch.GetMetricStatisticsInput{
MetricName: aws.String("CPUUtilization"),
StartTime: q.StartTime,
EndTime: q.EndTime,
Period: aws.Int32(300),
Namespace: aws.String("AWS/EC2"),
Statistics: []types.Statistic{types.StatisticSum},
Dimensions: []types.Dimension{
{
Name: aws.String("InstanceId"),
Value: aws.String("i-0dbd976daa9118015"),
},
},
})
if err != nil {
c.Error(err)
return
}
points := output.Datapoints
sort.Slice(points, func(i, j int) bool {
return points[i].Timestamp.Before(*points[j].Timestamp)
})
resp := Response{
Points: lo.Map(points, func(point types.Datapoint, i int) Point {
return Point{
DateTime: point.Timestamp.Format("15:04"),
Value: strconv.FormatFloat(*point.Sum, 'f', 2, 64),
Unit: string(point.Unit),
}
}),
}
c.JSON(http.StatusOK, resp)
}
type Response struct {
Points []Point `json:"points"`
}
type Point struct {
DateTime string `json:"dateTime"`
Value string `json:"value"`
Unit string `json:"unit"`
}
啟動Go專案,待稍後React專案啟動呼叫其API。
React
修改Chart.js
如下。
Chart.js
import { useEffect, useState } from "react";
import * as React from 'react';
import { LineChart, Line, XAxis, YAxis, Tooltip, Legend } from 'recharts';
import axios from 'axios';
export const Chart = () => {
const [points, setPoints] = useState([])
useEffect(() => {
axios.get('http://localhost:8080/cpu-utilization?startTime=2024-03-22T08%3A00%3A00&endTime=2024-03-22T10%3A00%3A00')
.then(resp => {
setPoints(resp.data.points)
})
.catch(error => {
console.log(error)
})
.finally(() => {
console.log('done')
})
},[])
return (
<LineChart width={600} height={200} data={points}>
<Line type="monotone" dataKey="value" stroke="#ee99cc" />
<XAxis dataKey="dateTime" />
<YAxis />
<Tooltip />
<Legend />
</LineChart>
)
}
啟動React專案,Chart component會呼叫後端API,並將回應結果透過Recharts顯示折線圖如下。
沒有留言:
張貼留言