初始提交:OCI 面板后端(含 GenAI 网关一期)
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
package oci
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/oracle/oci-go-sdk/v65/common"
|
||||
"github.com/oracle/oci-go-sdk/v65/monitoring"
|
||||
)
|
||||
|
||||
// trafficNamespace 是 VNIC 流量指标所在的 Monitoring 命名空间;
|
||||
// 指标由 OCI 自动上报,原始点 1 分钟一个,这里按天聚合。
|
||||
const (
|
||||
trafficNamespace = "oci_vcn"
|
||||
trafficResolution = "1440m"
|
||||
metricVnicInbound = "VnicFromNetworkBytes" // 实例收到的字节
|
||||
metricVnicOutbund = "VnicToNetworkBytes" // 实例发出的字节
|
||||
)
|
||||
|
||||
// TrafficQuery 是一次实例流量统计的条件。
|
||||
type TrafficQuery struct {
|
||||
Region string
|
||||
InstanceID string
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
}
|
||||
|
||||
// TrafficPoint 是一个聚合窗口(天)的流量字节数。
|
||||
type TrafficPoint struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Bytes float64 `json:"bytes"`
|
||||
}
|
||||
|
||||
// VnicTraffic 是单块 VNIC 的进出流量。
|
||||
type VnicTraffic struct {
|
||||
VnicID string `json:"vnicId"`
|
||||
InboundBytes float64 `json:"inboundBytes"`
|
||||
OutboundBytes float64 `json:"outboundBytes"`
|
||||
Inbound []TrafficPoint `json:"inbound"`
|
||||
Outbound []TrafficPoint `json:"outbound"`
|
||||
}
|
||||
|
||||
// InstanceTraffic 是实例全部 VNIC 的流量汇总。
|
||||
type InstanceTraffic struct {
|
||||
InstanceID string `json:"instanceId"`
|
||||
InboundBytes float64 `json:"inboundBytes"`
|
||||
OutboundBytes float64 `json:"outboundBytes"`
|
||||
Vnics []VnicTraffic `json:"vnics"`
|
||||
}
|
||||
|
||||
func (c *RealClient) monitoringClient(cred Credentials, region string) (monitoring.MonitoringClient, error) {
|
||||
mc, err := monitoring.NewMonitoringClientWithConfigurationProvider(provider(cred))
|
||||
if err != nil {
|
||||
return mc, fmt.Errorf("new monitoring client: %w", err)
|
||||
}
|
||||
applyProxy(&mc.BaseClient, cred)
|
||||
if region != "" {
|
||||
mc.SetRegion(normalizeRegion(region))
|
||||
}
|
||||
return mc, nil
|
||||
}
|
||||
|
||||
// SummarizeInstanceTraffic 实现 Client:逐 VNIC 查询进出流量并汇总。
|
||||
func (c *RealClient) SummarizeInstanceTraffic(ctx context.Context, cred Credentials, q TrafficQuery) (InstanceTraffic, error) {
|
||||
mc, err := c.monitoringClient(cred, q.Region)
|
||||
if err != nil {
|
||||
return InstanceTraffic{}, err
|
||||
}
|
||||
// VNIC 指标上报在实例所在 compartment,查询须用同一 compartment 才有数据
|
||||
vnics, compartmentID, err := c.instanceVnics(ctx, cred, q.Region, q.InstanceID)
|
||||
if err != nil {
|
||||
return InstanceTraffic{}, err
|
||||
}
|
||||
result := InstanceTraffic{InstanceID: q.InstanceID, Vnics: make([]VnicTraffic, 0, len(vnics))}
|
||||
for _, vnic := range vnics {
|
||||
vt := VnicTraffic{VnicID: deref(vnic.Id)}
|
||||
if vt.Inbound, err = summarizeVnicMetric(ctx, mc, compartmentID, vt.VnicID, metricVnicInbound, q); err != nil {
|
||||
return InstanceTraffic{}, err
|
||||
}
|
||||
if vt.Outbound, err = summarizeVnicMetric(ctx, mc, compartmentID, vt.VnicID, metricVnicOutbund, q); err != nil {
|
||||
return InstanceTraffic{}, err
|
||||
}
|
||||
vt.Inbound, vt.Outbound = orEmpty(vt.Inbound), orEmpty(vt.Outbound)
|
||||
vt.InboundBytes, vt.OutboundBytes = sumTraffic(vt.Inbound), sumTraffic(vt.Outbound)
|
||||
result.InboundBytes += vt.InboundBytes
|
||||
result.OutboundBytes += vt.OutboundBytes
|
||||
result.Vnics = append(result.Vnics, vt)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// summarizeVnicMetric 按天聚合查询单块 VNIC 的一个流量指标;
|
||||
// compartmentID 须是实例所在 compartment,指标数据挂在该 compartment 下。
|
||||
func summarizeVnicMetric(ctx context.Context, mc monitoring.MonitoringClient, compartmentID, vnicID, metric string, q TrafficQuery) ([]TrafficPoint, error) {
|
||||
query := fmt.Sprintf("%s[%s]{resourceId = %q}.sum()", metric, trafficResolution, vnicID)
|
||||
resolution := trafficResolution
|
||||
resp, err := mc.SummarizeMetricsData(ctx, monitoring.SummarizeMetricsDataRequest{
|
||||
CompartmentId: &compartmentID,
|
||||
SummarizeMetricsDataDetails: monitoring.SummarizeMetricsDataDetails{
|
||||
Namespace: common.String(trafficNamespace),
|
||||
Query: &query,
|
||||
StartTime: &common.SDKTime{Time: q.StartTime},
|
||||
EndTime: &common.SDKTime{Time: q.EndTime},
|
||||
Resolution: &resolution,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("summarize %s of vnic %s: %w", metric, vnicID, err)
|
||||
}
|
||||
var points []TrafficPoint
|
||||
for _, item := range resp.Items {
|
||||
for _, dp := range item.AggregatedDatapoints {
|
||||
if dp.Timestamp == nil || dp.Value == nil {
|
||||
continue
|
||||
}
|
||||
points = append(points, TrafficPoint{Timestamp: dp.Timestamp.Time, Bytes: *dp.Value})
|
||||
}
|
||||
}
|
||||
return orEmpty(points), nil
|
||||
}
|
||||
|
||||
func sumTraffic(points []TrafficPoint) float64 {
|
||||
var total float64
|
||||
for _, p := range points {
|
||||
total += p.Bytes
|
||||
}
|
||||
return total
|
||||
}
|
||||
Reference in New Issue
Block a user