Skip to content

Commit 37e3690

Browse files
committed
feat(service): add kube_service_ports metric
Signed-off-by: nahuel11500 <[email protected]>
1 parent 4fa3520 commit 37e3690

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

docs/metrics/service/service-metrics.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
| kube_service_spec_type | Gauge | Type about service | | `service`=&lt;service-name&gt; <br> `namespace`=&lt;service-namespace&gt; <br> `uid`=&lt;service-uid&gt; <br> `type`=&lt;ClusterIP\|NodePort\|LoadBalancer\|ExternalName&gt; | STABLE |
1010
| kube_service_spec_external_ip | Gauge | Service external ips. One series for each ip | | `service`=&lt;service-name&gt; <br> `namespace`=&lt;service-namespace&gt; <br> `uid`=&lt;service-uid&gt; <br> `external_ip`=&lt;external-ip&gt; | STABLE |
1111
| kube_service_status_load_balancer_ingress | Gauge | Service load balancer ingress status | | `service`=&lt;service-name&gt; <br> `namespace`=&lt;service-namespace&gt; <br> `uid`=&lt;service-uid&gt; <br> `ip`=&lt;load-balancer-ingress-ip&gt; <br> `hostname`=&lt;load-balancer-ingress-hostname&gt; | STABLE |
12+
| kube_service_ports | Gauge | Metric providing details about the ports exposed by services. | | `service`=&lt;service-name&gt; <br> `namespace`=&lt;service-namespace&gt; <br> `uid`=&lt;service-uid&gt; <br> `port_name`=&lt;service-port-name&gt; <br> `port_protocol`=&lt;service-port-protocol&gt; <br> `port_number`=&lt;service-port-number&gt; <br> `port_target`=&lt;service-port-target&gt; <br> `port_app_protocol`=&lt;service-port-appProtocol&gt; <br> `port_node_number`=&lt;service-node-port-number&gt; | EXPERIMENTAL |

internal/store/service.go

+44
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package store
1818

1919
import (
2020
"context"
21+
"strconv"
2122

2223
v1 "k8s.io/api/core/v1"
2324
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -184,6 +185,49 @@ func serviceMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gen
184185
}
185186
}),
186187
),
188+
*generator.NewFamilyGeneratorWithStability(
189+
"kube_service_ports",
190+
"Metric providing details about the ports exposed by services.",
191+
metric.Gauge,
192+
basemetrics.ALPHA,
193+
"",
194+
wrapSvcFunc(func(e *v1.Service) *metric.Family {
195+
ms := []*metric.Metric{}
196+
labelKeys := []string{"port_protocol", "port_number", "port_name", "port_target", "port_node_number", "port_app_protocol"}
197+
for _, port := range e.Spec.Ports {
198+
appProtocol := ""
199+
if port.AppProtocol != nil {
200+
appProtocol = *port.AppProtocol
201+
}
202+
var labelValues []string
203+
portNumber := strconv.FormatInt(int64(port.Port), 10)
204+
targetPort := port.TargetPort.String()
205+
nodePort := ""
206+
207+
if port.NodePort != 0 {
208+
nodePort = strconv.FormatInt(int64(port.NodePort), 10)
209+
}
210+
211+
labelValues = []string{
212+
string(port.Protocol),
213+
portNumber,
214+
port.Name,
215+
targetPort,
216+
nodePort,
217+
appProtocol,
218+
}
219+
220+
ms = append(ms, &metric.Metric{
221+
LabelValues: labelValues,
222+
LabelKeys: labelKeys,
223+
Value: 1,
224+
})
225+
}
226+
return &metric.Family{
227+
Metrics: ms,
228+
}
229+
}),
230+
),
187231
}
188232
}
189233

internal/store/service_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
v1 "k8s.io/api/core/v1"
2424
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
"k8s.io/apimachinery/pkg/util/intstr"
2526

2627
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
2728
)
@@ -44,6 +45,8 @@ func TestServiceStore(t *testing.T) {
4445
# TYPE kube_service_spec_external_ip gauge
4546
# HELP kube_service_status_load_balancer_ingress [STABLE] Service load balancer ingress status
4647
# TYPE kube_service_status_load_balancer_ingress gauge
48+
# HELP kube_service_ports Metric providing details about the ports exposed by services.
49+
# TYPE kube_service_ports gauge
4750
`
4851
cases := []generateMetricsTestCase{
4952
{
@@ -68,11 +71,13 @@ func TestServiceStore(t *testing.T) {
6871
# HELP kube_service_info [STABLE] Information about service.
6972
# HELP kube_service_labels [STABLE] Kubernetes labels converted to Prometheus labels.
7073
# HELP kube_service_spec_type [STABLE] Type about service.
74+
# HELP kube_service_ports Metric providing details about the ports exposed by services.
7175
# TYPE kube_service_annotations gauge
7276
# TYPE kube_service_created gauge
7377
# TYPE kube_service_info gauge
7478
# TYPE kube_service_labels gauge
7579
# TYPE kube_service_spec_type gauge
80+
# TYPE kube_service_ports gauge
7681
kube_service_created{namespace="default",service="test-service1",uid="uid1"} 1.5e+09
7782
kube_service_info{cluster_ip="1.2.3.4",external_name="",external_traffic_policy="",load_balancer_ip="",namespace="default",service="test-service1",uid="uid1"} 1
7883
kube_service_spec_type{namespace="default",service="test-service1",type="ClusterIP",uid="uid1"} 1
@@ -83,6 +88,7 @@ func TestServiceStore(t *testing.T) {
8388
"kube_service_info",
8489
"kube_service_labels",
8590
"kube_service_spec_type",
91+
"kube_service_ports",
8692
},
8793
},
8894
{
@@ -259,6 +265,35 @@ func TestServiceStore(t *testing.T) {
259265
kube_service_spec_type{namespace="default",service="test-service8",uid="uid8",type="LoadBalancer"} 1
260266
`,
261267
},
268+
269+
{
270+
Obj: &v1.Service{
271+
ObjectMeta: metav1.ObjectMeta{
272+
Name: "test-service9",
273+
CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)},
274+
Namespace: "default",
275+
UID: "uid9",
276+
Labels: map[string]string{
277+
"app": "example9",
278+
},
279+
},
280+
Spec: v1.ServiceSpec{
281+
ClusterIP: "1.2.3.14",
282+
LoadBalancerIP: "1.2.3.15",
283+
Type: v1.ServiceTypeLoadBalancer,
284+
ExternalTrafficPolicy: "Local",
285+
Ports: []v1.ServicePort{
286+
{Port: 80, Protocol: v1.ProtocolTCP, TargetPort: intstr.FromInt(8080), Name: "http", NodePort: 65000, AppProtocol: func(s string) *string { return &s }("grpc")},
287+
},
288+
},
289+
},
290+
Want: metadata + `
291+
kube_service_created{namespace="default",service="test-service9",uid="uid9"} 1.5e+09
292+
kube_service_info{cluster_ip="1.2.3.14",external_name="",external_traffic_policy="Local",load_balancer_ip="1.2.3.15",namespace="default",service="test-service9",uid="uid9"} 1
293+
kube_service_spec_type{namespace="default",service="test-service9",uid="uid9",type="LoadBalancer"} 1
294+
kube_service_ports{namespace="default",port_app_protocol="grpc",port_name="http",port_node_number="65000",port_number="80",port_protocol="TCP",port_target="8080",service="test-service9",uid="uid9"} 1
295+
`,
296+
},
262297
}
263298
for i, c := range cases {
264299
c.Func = generator.ComposeMetricGenFuncs(serviceMetricFamilies(nil, nil))

0 commit comments

Comments
 (0)