pkg/k8score/metrics.go
Rama main · réplica de lectura del repositorio original.
package k8score
import (
"context"
"errors"
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
)
// MetricsAPIGroup is the Kubernetes resource metrics API group.
const MetricsAPIGroup = "metrics.k8s.io"
var (
// PodMetricsGVR is the v1beta1 compatibility default used by GetPodMetrics.
// Discovery-aware callers should use GetPodMetricsWithGVR.
PodMetricsGVR = schema.GroupVersionResource{Group: MetricsAPIGroup, Version: "v1beta1", Resource: "pods"}
// NodeMetricsGVR is the v1beta1 compatibility default used by GetNodeMetrics.
// Discovery-aware callers should use GetNodeMetricsWithGVR.
NodeMetricsGVR = schema.GroupVersionResource{Group: MetricsAPIGroup, Version: "v1beta1", Resource: "nodes"}
// ErrMetricsAPINotDiscovered indicates that API discovery did not return a
// usable metrics API version.
ErrMetricsAPINotDiscovered = errors.New("metrics API is not discovered")
)
// MetricsGVRResolver resolves the currently served GVR for a metrics resource.
type MetricsGVRResolver func(resource string) (schema.GroupVersionResource, bool)
// PodMetrics represents metrics for a single pod.
type PodMetrics struct {
Metadata MetricsMeta `json:"metadata"`
Timestamp string `json:"timestamp"`
Window string `json:"window"`
Containers []ContainerMetrics `json:"containers"`
}
// NodeMetrics represents metrics for a single node.
type NodeMetrics struct {
Metadata MetricsMeta `json:"metadata"`
Timestamp string `json:"timestamp"`
Window string `json:"window"`
Usage ResourceUsage `json:"usage"`
}
// MetricsMeta contains metadata for metrics objects.
type MetricsMeta struct {
Name string `json:"name"`
Namespace string `json:"namespace,omitempty"`
CreationTimestamp string `json:"creationTimestamp"`
}
// ContainerMetrics represents metrics for a single container.
type ContainerMetrics struct {
Name string `json:"name"`
Usage ResourceUsage `json:"usage"`
}
// ResourceUsage contains CPU and memory usage.
type ResourceUsage struct {
CPU string `json:"cpu"`
Memory string `json:"memory"`
}
// GetPodMetrics fetches metrics for a specific pod from the metrics.k8s.io API.
func GetPodMetrics(ctx context.Context, client dynamic.Interface, namespace, name string) (*PodMetrics, error) {
return GetPodMetricsWithGVR(ctx, client, PodMetricsGVR, namespace, name)
}
// GetPodMetricsWithGVR fetches metrics using a discovered metrics API version.
func GetPodMetricsWithGVR(ctx context.Context, client dynamic.Interface, gvr schema.GroupVersionResource, namespace, name string) (*PodMetrics, error) {
result, err := client.Resource(gvr).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("failed to get pod metrics: %w", err)
}
metrics := &PodMetrics{}
if meta, ok := result.Object["metadata"].(map[string]any); ok {
metrics.Metadata.Name, _ = meta["name"].(string)
metrics.Metadata.Namespace, _ = meta["namespace"].(string)
metrics.Metadata.CreationTimestamp, _ = meta["creationTimestamp"].(string)
}
metrics.Timestamp, _ = result.Object["timestamp"].(string)
metrics.Window, _ = result.Object["window"].(string)
if containers, ok := result.Object["containers"].([]any); ok {
for _, c := range containers {
if container, ok := c.(map[string]any); ok {
cm := ContainerMetrics{}
cm.Name, _ = container["name"].(string)
if usage, ok := container["usage"].(map[string]any); ok {
cm.Usage.CPU, _ = usage["cpu"].(string)
cm.Usage.Memory, _ = usage["memory"].(string)
}
metrics.Containers = append(metrics.Containers, cm)
}
}
}
return metrics, nil
}
// GetNodeMetrics fetches metrics for a specific node from the metrics.k8s.io API.
func GetNodeMetrics(ctx context.Context, client dynamic.Interface, name string) (*NodeMetrics, error) {
return GetNodeMetricsWithGVR(ctx, client, NodeMetricsGVR, name)
}
// GetNodeMetricsWithGVR fetches metrics using a discovered metrics API version.
func GetNodeMetricsWithGVR(ctx context.Context, client dynamic.Interface, gvr schema.GroupVersionResource, name string) (*NodeMetrics, error) {
result, err := client.Resource(gvr).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("failed to get node metrics: %w", err)
}
metrics := &NodeMetrics{}
if meta, ok := result.Object["metadata"].(map[string]any); ok {
metrics.Metadata.Name, _ = meta["name"].(string)
metrics.Metadata.CreationTimestamp, _ = meta["creationTimestamp"].(string)
}
metrics.Timestamp, _ = result.Object["timestamp"].(string)
metrics.Window, _ = result.Object["window"].(string)
if usage, ok := result.Object["usage"].(map[string]any); ok {
metrics.Usage.CPU, _ = usage["cpu"].(string)
metrics.Usage.Memory, _ = usage["memory"].(string)
}
return metrics, nil
}