Refactor EndpointsSlice to reduce complexity

This commit is contained in:
Omar Nasser 2025-08-20 11:54:50 +03:00
parent 66296c3819
commit b08e288684
1 changed files with 208 additions and 181 deletions

View File

@ -40,205 +40,232 @@ var (
func endpointSliceMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator { func endpointSliceMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator {
return []generator.FamilyGenerator{ return []generator.FamilyGenerator{
*generator.NewFamilyGeneratorWithStability( createEndpointsSliceInfo(),
"kube_endpointslice_info", createEndpointsSliceCreated(),
"Information about endpointslice.", createEndpointsSliceHints(),
metric.Gauge, createEndpointsSliceEndpoints(),
basemetrics.ALPHA, createEndpointSlicePorts(),
"", createEndpointsSliceAnnotations(allowAnnotationsList),
wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family { createEndpointsSliceLabels(allowLabelsList),
}
}
m := metric.Metric{ func createEndpointsSliceInfo() generator.FamilyGenerator {
LabelKeys: []string{"addresstype"}, return *generator.NewFamilyGeneratorWithStability(
LabelValues: []string{string(s.AddressType)}, "kube_endpointslice_info",
Value: 1, "Information about endpointslice.",
} metric.Gauge,
return &metric.Family{Metrics: []*metric.Metric{&m}} basemetrics.ALPHA,
}), "",
), wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family {
*generator.NewFamilyGeneratorWithStability(
"kube_endpointslice_created",
"Unix creation timestamp",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family {
ms := []*metric.Metric{}
if !s.CreationTimestamp.IsZero() {
ms = append(ms, &metric.Metric{
Value: float64(s.CreationTimestamp.Unix()),
})
}
return &metric.Family{
Metrics: ms,
}
}),
),
*generator.NewFamilyGeneratorWithStability(
"kube_endpointslice_endpoints_hints",
"Topology routing hints attached to endpoints",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family {
m := []*metric.Metric{}
for _, ep := range e.Endpoints {
// Hint is populated when the endpoint is configured to be zone aware and preferentially route requests to its local zone.
// If there is no hint, skip this metric
if ep.Hints != nil && len(ep.Hints.ForZones) > 0 {
var (
labelKeys,
labelValues []string
)
// Per Docs. m := metric.Metric{
// This must contain at least one address but no more than LabelKeys: []string{"addresstype"},
// 100. These are all assumed to be fungible and clients may choose to only LabelValues: []string{string(s.AddressType)},
// use the first element. Refer to: https://issue.k8s.io/106267 Value: 1,
labelKeys = append(labelKeys, "address") }
labelValues = append(labelValues, ep.Addresses[0]) return &metric.Family{Metrics: []*metric.Metric{&m}}
}),
)
}
for _, zone := range ep.Hints.ForZones { func createEndpointsSliceCreated() generator.FamilyGenerator {
m = append(m, &metric.Metric{ return *generator.NewFamilyGeneratorWithStability(
LabelKeys: append(labelKeys, "for_zone"), "kube_endpointslice_created",
LabelValues: append(labelValues, zone.Name), "Unix creation timestamp",
Value: 1, metric.Gauge,
}) basemetrics.ALPHA,
} "",
} wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family {
} ms := []*metric.Metric{}
return &metric.Family{ if !s.CreationTimestamp.IsZero() {
Metrics: m, ms = append(ms, &metric.Metric{
} Value: float64(s.CreationTimestamp.Unix()),
}), })
), }
*generator.NewFamilyGeneratorWithStability( return &metric.Family{
"kube_endpointslice_endpoints", Metrics: ms,
"Endpoints attached to the endpointslice.", }
metric.Gauge, }),
basemetrics.ALPHA, )
"", }
wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family {
m := []*metric.Metric{}
for _, ep := range e.Endpoints {
var ready, serving, terminating, hostname, targetrefKind, targetrefName, targetrefNamespace, endpointNodename, endpointZone string func createEndpointsSliceHints() generator.FamilyGenerator {
return *generator.NewFamilyGeneratorWithStability(
"kube_endpointslice_endpoints_hints",
"Topology routing hints attached to endpoints",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family {
m := []*metric.Metric{}
for _, ep := range e.Endpoints {
// Hint is populated when the endpoint is configured to be zone aware and preferentially route requests to its local zone.
// If there is no hint, skip this metric
if ep.Hints != nil && len(ep.Hints.ForZones) > 0 {
var (
labelKeys,
labelValues []string
)
if ep.Conditions.Ready != nil { // Per Docs.
ready = strconv.FormatBool(*ep.Conditions.Ready) // This must contain at least one address but no more than
} // 100. These are all assumed to be fungible and clients may choose to only
// use the first element. Refer to: https://issue.k8s.io/106267
if ep.Conditions.Serving != nil { labelKeys = append(labelKeys, "address")
serving = strconv.FormatBool(*ep.Conditions.Serving) labelValues = append(labelValues, ep.Addresses[0])
}
if ep.Conditions.Terminating != nil {
serving = strconv.FormatBool(*ep.Conditions.Terminating)
}
if ep.Hostname != nil {
hostname = *ep.Hostname
}
if ep.TargetRef != nil {
targetrefKind = ep.TargetRef.Kind
targetrefName = ep.TargetRef.Name
targetrefNamespace = ep.TargetRef.Namespace
}
if ep.NodeName != nil {
endpointNodename = *ep.NodeName
}
if ep.Zone != nil {
endpointZone = *ep.Zone
}
labelKeys := []string{"ready", "serving", "hostname", "terminating", "targetref_kind", "targetref_name", "targetref_namespace", "endpoint_nodename", "endpoint_zone", "address"}
labelValues := []string{ready, serving, terminating, hostname, targetrefKind, targetrefName, targetrefNamespace, endpointNodename, endpointZone}
for _, address := range ep.Addresses {
newlabelValues := make([]string, len(labelValues))
copy(newlabelValues, labelValues)
newlabelValues = append(newlabelValues, address)
for _, zone := range ep.Hints.ForZones {
m = append(m, &metric.Metric{ m = append(m, &metric.Metric{
LabelKeys: labelKeys, LabelKeys: append(labelKeys, "for_zone"),
LabelValues: newlabelValues, LabelValues: append(labelValues, zone.Name),
Value: 1, Value: 1,
}) })
} }
} }
return &metric.Family{ }
Metrics: m, return &metric.Family{
} Metrics: m,
}), }
), }),
)
}
func createEndpointsSliceEndpoints() generator.FamilyGenerator {
return *generator.NewFamilyGeneratorWithStability(
"kube_endpointslice_endpoints",
"Endpoints attached to the endpointslice.",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family {
m := []*metric.Metric{}
for _, ep := range e.Endpoints {
var ready, serving, terminating, hostname, targetrefKind, targetrefName, targetrefNamespace, endpointNodename, endpointZone string
if ep.Conditions.Ready != nil {
ready = strconv.FormatBool(*ep.Conditions.Ready)
}
if ep.Conditions.Serving != nil {
serving = strconv.FormatBool(*ep.Conditions.Serving)
}
if ep.Conditions.Terminating != nil {
serving = strconv.FormatBool(*ep.Conditions.Terminating)
}
if ep.Hostname != nil {
hostname = *ep.Hostname
}
if ep.TargetRef != nil {
targetrefKind = ep.TargetRef.Kind
targetrefName = ep.TargetRef.Name
targetrefNamespace = ep.TargetRef.Namespace
}
if ep.NodeName != nil {
endpointNodename = *ep.NodeName
}
if ep.Zone != nil {
endpointZone = *ep.Zone
}
labelKeys := []string{"ready", "serving", "hostname", "terminating", "targetref_kind", "targetref_name", "targetref_namespace", "endpoint_nodename", "endpoint_zone", "address"}
labelValues := []string{ready, serving, terminating, hostname, targetrefKind, targetrefName, targetrefNamespace, endpointNodename, endpointZone}
for _, address := range ep.Addresses {
newlabelValues := make([]string, len(labelValues))
copy(newlabelValues, labelValues)
newlabelValues = append(newlabelValues, address)
*generator.NewFamilyGeneratorWithStability(
"kube_endpointslice_ports",
"Ports attached to the endpointslice.",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family {
m := []*metric.Metric{}
for _, port := range e.Ports {
m = append(m, &metric.Metric{ m = append(m, &metric.Metric{
LabelValues: []string{*port.Name, string(*port.Protocol), strconv.FormatInt(int64(*port.Port), 10)}, LabelKeys: labelKeys,
LabelKeys: []string{"port_name", "port_protocol", "port_number"}, LabelValues: newlabelValues,
Value: 1, Value: 1,
}) })
} }
return &metric.Family{ }
Metrics: m, return &metric.Family{
} Metrics: m,
}), }
), }),
*generator.NewFamilyGeneratorWithStability( )
descEndpointSliceAnnotationsName, }
descEndpointSliceAnnotationsHelp,
metric.Gauge, func createEndpointSlicePorts() generator.FamilyGenerator {
basemetrics.ALPHA, return *generator.NewFamilyGeneratorWithStability(
"", "kube_endpointslice_ports",
wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family { "Ports attached to the endpointslice.",
if len(allowAnnotationsList) == 0 { metric.Gauge,
return &metric.Family{} basemetrics.ALPHA,
} "",
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList) wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family {
return &metric.Family{ m := []*metric.Metric{}
Metrics: []*metric.Metric{ for _, port := range e.Ports {
{ m = append(m, &metric.Metric{
LabelKeys: annotationKeys, LabelValues: []string{*port.Name, string(*port.Protocol), strconv.FormatInt(int64(*port.Port), 10)},
LabelValues: annotationValues, LabelKeys: []string{"port_name", "port_protocol", "port_number"},
Value: 1, Value: 1,
}, })
}
return &metric.Family{
Metrics: m,
}
}),
)
}
func createEndpointsSliceAnnotations(allowAnnotationsList []string) generator.FamilyGenerator {
return *generator.NewFamilyGeneratorWithStability(
descEndpointSliceAnnotationsName,
descEndpointSliceAnnotationsHelp,
metric.Gauge,
basemetrics.ALPHA,
"",
wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
{
LabelKeys: annotationKeys,
LabelValues: annotationValues,
Value: 1,
}, },
} },
}), }
), }),
*generator.NewFamilyGeneratorWithStability( )
descEndpointSliceLabelsName, }
descEndpointSliceLabelsHelp,
metric.Gauge, func createEndpointsSliceLabels(allowLabelsList []string) generator.FamilyGenerator {
basemetrics.ALPHA, return *generator.NewFamilyGeneratorWithStability(
"", descEndpointSliceLabelsName,
wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family { descEndpointSliceLabelsHelp,
if len(allowLabelsList) == 0 { metric.Gauge,
return &metric.Family{} basemetrics.ALPHA,
} "",
labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList) wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family {
return &metric.Family{ if len(allowLabelsList) == 0 {
Metrics: []*metric.Metric{ return &metric.Family{}
{ }
LabelKeys: labelKeys, labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList)
LabelValues: labelValues, return &metric.Family{
Value: 1, Metrics: []*metric.Metric{
}, {
LabelKeys: labelKeys,
LabelValues: labelValues,
Value: 1,
}, },
} },
}), }
), }),
} )
} }
func wrapEndpointSliceFunc(f func(*discoveryv1.EndpointSlice) *metric.Family) func(interface{}) *metric.Family { func wrapEndpointSliceFunc(f func(*discoveryv1.EndpointSlice) *metric.Family) func(interface{}) *metric.Family {